Baixe o app para aproveitar ainda mais
Prévia do material em texto
Treinamento em C# WebDeveloper Aula 17 Segunda-feira, 10 de Dezembro de 2018 Acesso a banco de dados com EntityFramework. Criando uma nova solução em branco: Organizando a solution em pastas: 0 - Modelagem de entidades Bibliotecas de Classes (.NET Framework) using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Projeto.Entities { public class Produto { //propriedades [prop] + 2x[tab] public int IdProduto { get; set; } public string Nome { get; set; } public decimal Preco { get; set; } public int Quantidade { get; set; } //relacionamento -> TER 1 public Estoque Estoque { get; set; } //construtor default [ctor] + 2x[tab] public Produto() { //vazio } //sobrecarga de construtor (overloading) public Produto(int idProduto, string nome, decimal preco, int quantidade) { IdProduto = idProduto; Nome = nome; Preco = preco; Quantidade = quantidade; } //sobrescrita do método ToString() public override string ToString() { return $"Id: {IdProduto}, Nome: {Nome}, Preço: {Preco}, Quantidade: {Quantidade}"; } } } ---------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Projeto.Entities { public class Estoque { //propriedades public int IdEstoque { get; set; } public string Nome { get; set; } //relacionamento -> TER MUITOS public List<Produto> Produtos { get; set; } //construtor default [ctor] + 2x[tab] public Estoque() { //vazio } //sobrecarga de construtores (overloading) public Estoque(int idEstoque, string nome) { IdEstoque = idEstoque; Nome = nome; } //sobrescrita de método (override) public override string ToString() { return $"Id: {IdEstoque}, Nome: {Nome}"; } } } 1 - Camada de Apresentação Projeto Asp.NET WebAPI 2 - Camada de Regras de Negócio 3 - Camada de Acesso a dados Biblioteca de Classes .NET Framework Instalando o EntityFramework Gerenciador de pacotes do NuGet Criando a base de dados MDF - Master Database File Mapeando a connectionstring no arquivo Web.config.xml <connectionStrings> <add name="AULA17" connectionString="Data Source=(LocalDB)\MSSQLLocalDB; AttachDbFilename=C:\Users\COTI\Desktop\Aula_10.12.18\Aula17\ Projeto.Presentation\App_Data\Banco.mdf;Integrated Security=True" /> </connectionStrings> ----------------------- Entity Framework O Microsoft® ADO.NET Entity Framework é um framework do tipo ORM (Object/Relational Mapping) que permite aos desenvolvedores trabalhar com dados relacionais como objetos de domínio específico, eliminando a necessidade de maior parte dos códigos de acesso de dados que os desenvolvedores geralmente precisam escrever. Com o Entity Framework, os desenvolvedores podem lançar consultas usando expressões LAMBDA, e depois recuperar e manipular dados como objetos fortemente tipificados. A implementação do ORM do Entity Framework fornece serviços como rastreamento de alterações, resolução de identidades, lazy loading e tradução de consultas para que os desenvolvedores possam se concentrar na lógica de negócios de seus aplicativos em vez dos princípios básicos de acesso a dados. Passo 1) Mapear as classes de entidade Para cada classe de entidade iremos criar uma classe de mapeamento com o objetivo de "traduzir" a entidade (Orientado a Objeto) para o modelo relacional de banco de dados. Mapeando a classe Estoque: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.Entity.ModelConfiguration; //importando.. using Projeto.Entities; //importando.. namespace Projeto.Repository.Mappings { //classe de mapeamento para a entidade Estoque public class EstoqueMap : EntityTypeConfiguration<Estoque> { //construtor public EstoqueMap() { //nome da tabela ToTable("Estoque"); //chave primária HasKey(e => e.IdEstoque); //mapear cada campo da tabela Property(e => e.IdEstoque) //propridade da classe .HasColumnName("IdEstoque"); //campo da tabela Property(e => e.Nome) //propriedade da classe .HasColumnName("Nome") //campo da tabela .HasMaxLength(100) //nvarchar(100) .IsRequired(); //not null } } } Mapeando a classe Produto: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.Entity.ModelConfiguration; //importando.. using Projeto.Entities; //importando.. namespace Projeto.Repository.Mappings { //classe de mapeamento para a entidade Produto.. public class ProdutoMap : EntityTypeConfiguration<Produto> { //construtor [ctor] + 2x[tab] public ProdutoMap() { //nome da tabela ToTable("Produto"); //chave primária HasKey(p => p.IdProduto); //mapear cada coluna da tabela.. Property(p => p.IdProduto) .HasColumnName("IdProduto"); Property(p => p.Nome) .HasColumnName("Nome") .HasMaxLength(100) .IsRequired(); Property(p => p.Preco) .HasColumnName("Preco") .HasPrecision(18, 2) .IsRequired(); Property(p => p.Quantidade) .HasColumnName("Quantidade") .IsRequired(); } } } Exercitando o modelo de banco de dados: Estoque IdEstoque Nome 1 Estoque X 2 Estoque Y Produto IdProduto Nome Preco Quantidade IdEstoque 1 Produto A 100 10 1 2 Produto B 150 15 1 3 Produto C 200 20 2 * Para criarmos o relacionamento acima, o EntityFramework precisa que declaremos uma propriedade (chave estrangeira) na classe Produto: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Projeto.Entities { public class Produto { //propriedades [prop] + 2x[tab] public int IdProduto { get; set; } public string Nome { get; set; } public decimal Preco { get; set; } public int Quantidade { get; set; } public int IdEstoque { get; set; } //relacionamento -> TER 1 public Estoque Estoque { get; set; } //construtor default [ctor] + 2x[tab] public Produto() { //vazio } //sobrecarga de construtor (overloading) public Produto(int idProduto, string nome, decimal preco, int quantidade) { IdProduto = idProduto; Nome = nome; Preco = preco; Quantidade = quantidade; } //sobrescrita do método ToString() public override string ToString() { return $"Id: {IdProduto}, Nome: {Nome}, Preço: {Preco}, Quantidade: {Quantidade}"; } } } Voltando na classe ProdutoMap: Mapeando o relacionamento using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.Entity.ModelConfiguration; //importando.. using Projeto.Entities; //importando.. namespace Projeto.Repository.Mappings { //classe de mapeamento para a entidade Produto.. public class ProdutoMap : EntityTypeConfiguration<Produto> { //construtor[ctor] + 2x[tab] public ProdutoMap() { //nome da tabela ToTable("Produto"); //chave primária HasKey(p => p.IdProduto); //mapear cada coluna da tabela.. Property(p => p.IdProduto) .HasColumnName("IdProduto"); Property(p => p.Nome) .HasColumnName("Nome") .HasMaxLength(100) .IsRequired(); Property(p => p.Preco) .HasColumnName("Preco") .HasPrecision(18, 2) .IsRequired(); Property(p => p.Quantidade) .HasColumnName("Quantidade") .IsRequired(); Property(p => p.IdEstoque) .HasColumnName("IdEstoque") .IsRequired(); //mapear o relacionamento HasRequired(p => p.Estoque) //Produto TEM 1 Estoque .WithMany(e => e.Produtos) //Estoque TEM Muitos Produtos .HasForeignKey(p => p.IdEstoque) //chave estrangeira .WillCascadeOnDelete(false); //não é delete cascade, } } } CodeFirst Gerar o conteúdo da base de dados a partir do mapeamento das classes de entidade do projeto. Criando uma classe para configurar o acesso ao banco de dados através do EntityFramework: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Projeto.Repository.Context { public class DataContext { } } A classe denominada DataContext será utilizada para configurar o acesso ao banco de dados por meio do entityframework. Esta classe é chamada de "contexto" pois reúne toda a configuração necessária para que o entityframework possa conectar-se e possa "trabalhar" em uma base de dados. ** Adicionando referencia para System.Configuration using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Configuration; //connectionstring using System.Data.Entity; //entityframework using Projeto.Entities; //classes de entidade using Projeto.Repository.Mappings; //classe de mapeamento namespace Projeto.Repository.Context { //Regra 1) Herdar DbContext public class DataContext : DbContext { //Regra 2) Informar para a superclasse 'DbContext' o caminho //da connectionstring do banco de dados //declare um construtor e passar para o construtor da classe //DbContext o caminho da connectionstring public DataContext() : base(ConfigurationManager.ConnectionStrings ["AULA17"].ConnectionString) { } //Regra 3) Sobrescrever do método OnModelCreating //Neste método iremos definir para a classe DbContext cada //classe de mapeamento ORM criada no projeto protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new EstoqueMap()); modelBuilder.Configurations.Add(new ProdutoMap()); } //Regra 4) Declarar um set/get para cada classe de entidade //utilizando a classe DbSet do EntityFramework //O DbSet será utilizado para executar os comandos de consulta //na base de dados para cada classe de entidade (LAMBDA) public DbSet<Estoque> Estoque { get; set; } public DbSet<Produto> Produto { get; set; } } } Migrations Ferramenta do EntityFramework capaz de a partir do modelo de entidades e mapeamentos gerar e atualizar o conteúdo das tabelas do banco de dados Selecione o Projeto.Repository Ativando o recurso do "Migrations" PM> enable-migrations -force Checking if the context targets an existing database... Code First Migrations enabled for project Projeto.Repository. Foi criado a classe abaixo: namespace Projeto.Repository.Migrations { using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration <Projeto.Repository.Context.DataContext> { public Configuration() { AutomaticMigrationsEnabled = false; } protected override void Seed (Projeto.Repository.Context.DataContext context) { // This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method // to avoid creating duplicate seed data. } } } Concedendo permissão para CREATE, ALTER ou DROP da base de dados: namespace Projeto.Repository.Migrations { using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration <Projeto.Repository.Context.DataContext> { public Configuration() { AutomaticMigrationsEnabled = true; //CREATE, ALTER AutomaticMigrationDataLossAllowed = true; //DROP } protected override void Seed (Projeto.Repository.Context.DataContext context) { // This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method // to avoid creating duplicate seed data. } } } Atualizando o conteúdo do banco de dados: PM> update-database -verbose Criando as classes para persistência em banco de dados ** Primeiro, iremos criar uma classe de persistência genérica: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Projeto.Repository.Context; //importando.. using System.Data.Entity; //importando.. namespace Projeto.Repository.Persistence { public class BaseRepository<T> where T : class { public void Inserir(T obj) { using (DataContext ctx = new DataContext()) { ctx.Entry(obj).State = EntityState.Added; //insert ctx.SaveChanges(); //executando.. } } public void Atualizar(T obj) { using (DataContext ctx = new DataContext()) { ctx.Entry(obj).State = EntityState.Modified; //update ctx.SaveChanges(); //executando.. } } public void Excluir(T obj) { using (DataContext ctx = new DataContext()) { ctx.Entry(obj).State = EntityState.Deleted; //delete ctx.SaveChanges(); //executando.. } } public List<T> Consultar() { using (DataContext ctx = new DataContext()) { return ctx.Set<T>().ToList(); } } public T ConsultarPorId(int id) { using (DataContext ctx = new DataContext()) { return ctx.Set<T>().Find(id); } } } } Continua... 19
Compartilhar