Designar tabela para propriedade Entity Framework 4.1
-
segunda-feira, 20 de agosto de 2012 14:29
Olá pessoal, bom dia!
Criei um projeto com o entity framework 4.1 CodeFirst e ele está gerando as seguintes tabelas:
Clientes (id, Nome, Id_Vendedor)
Vendedores(id, Nome)
Pedidos (Id, Id_Cliente, Id_Vendedor)
Na minha classe Vendedor, eu tenho o seguinte:
Public Class Vendedor
property Clientes As ICollection(of Cliente)
End Class
Como vocês podem perceber, o entity na hora de gerar as tabelas e os campos, está colocando uma chave estrangeira na tabela Clientes (Id_Vendedor) para popular a propriedade Clientes que está na classe Vendedor, só que a minha intenção é eliminar essa chave estrangeira e popular a propriedade Clientes da classe Vendedor pela tabela de Pedido.
Como trazer os clientes referentes ao vendedor da tabela Pedido e popular a propriedade Clientes da classe Vendedor?Abaixo, o codigo do projeto:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace CarrinhoDeCompras.Models { public class Pedido { public Pedido() { Itens = new List<ItemPedido>(); } public int Id { get; set; } public Vendedor Vendedor { get; set; } public Cliente Cliente { get; set; } public virtual ICollection<ItemPedido> Itens { get; set; } } } ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace CarrinhoDeCompras.Models { [Table("ItensPedido")] public class ItemPedido { public int Id { get; set; } public Produto Produto { get; set; } public int Quantidade { get; set; } public Pedido Pedido { get; set; } } } ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace CarrinhoDeCompras.Models { [Table("Produtos")] public class Produto { public int Id { get; set; } public string Descricao { get; set; } public string CodigoDeBarras { get; set; } public int Quantidade { get; set; } } } ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace CarrinhoDeCompras.Models { [Table("Pessoas")] public class Pessoa { public int Id { get; set; } public string Nome { get; set; } } } ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace CarrinhoDeCompras.Models { [Table("PessoasFisicas")] public class PessoaFisica: Pessoa { public string CPF { get; set; } } } =============================================== using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace CarrinhoDeCompras.Models { [Table("Clientes")] public class Cliente : PessoaFisica { public decimal Saldo { get; set; } public virtual ICollection<Pedido> Pedidos { get; set; } } } =============================================== using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace CarrinhoDeCompras.Models { [Table("Funcionarios")] public class Funcionario : PessoaFisica { public decimal Salario { get; set; } } } =============================================== using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace CarrinhoDeCompras.Models { [Table("Vendedores")] public class Vendedor : Funcionario { public int Comissao { get; set; } public virtual ICollection<Cliente> Clientes { get; set; } } } =============================================== using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.Entity; namespace CarrinhoDeCompras.Models { public class Contexto : DbContext { //public Contexto() : base("CarrinhoDeCompras") { } public DbSet<Pessoa> Pessoas { get; set; } public DbSet<PessoaFisica> PessoasFisicas { get; set; } public DbSet<Cliente> Clientes { get; set; } public DbSet<Funcionario> Funcionarios { get; set; } public DbSet<Vendedor> Vendedores { get; set; } public DbSet<Produto> Produtos { get; set; } public DbSet<Pedido> Pedidos { get; set; } public DbSet<ItemPedido> ItensPedido { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { } } }
vlw
- Editado RodrigoPorto segunda-feira, 20 de agosto de 2012 14:49
Todas as Respostas
-
segunda-feira, 20 de agosto de 2012 15:12Moderador
Ola Rodrigo,
Voce pode fazer os relacionamentos usando atributos ou fluent, eu pessoalmente prefiro usar atributos, se quiser saber mais sobre Fluent de uma olhada aqui: http://stackoverflow.com/questions/7548391/entity-framework-4-1-fluent-mapping-foreign-key-and-the-foreign-object-with-a-st
[Table("Clientes")] public class Cliente { [Key, Column("id")] public int ID { get; set; } [Column("Id_Vendendor")] public int VendedorID { get; set; } [Column("Nome")] public string Nome { get; set; } [ForeignKey("VendedorID")] public Vendedor Vendedor { get; set; } } public class Vendedor { [Key, Column("id")] public int ID { get; set; } [Column("Nome")] public string Nome { get; set; } [InverseProperty("VendedorID")] public ICollection<Cliente> Clientes { get; set; } }Mas, ja avisando esse tipo de relacionamento normalmente acaba gerando um codigo redundante, ja que toda vez q carregar os Clientes ira carregar o vendedor que ira carregar novamente o cliente e por ai vai...
Se for possivel utilize um metodo para efetuar a consulta dos cliente conforme for necessário:
[Table("Clientes")] public class Cliente { [Key, Column("id")] public int ID { get; set; } [Column("Id_Vendendor")] public int VendedorID { get; set; } [Column("Nome")] public string Nome { get; set; } [ForeignKey("VendedorID")] public Vendedor Vendedor { get; set; } } public class Vendedor { [Key, Column("id")] public int ID { get; set; } [Column("Nome")] public string Nome { get; set; } public IEnumerable<Cliente> GetClientes(DbContext context) { return context.Set<Cliente>().Where(item => item.VendedorID == this.ID).ToArray(); } }Microsoft Community Contributor
-
segunda-feira, 20 de agosto de 2012 15:28
Rui Santos, muito obrigado por sua atenção. Nâo estou com o .Net aqui. Quando eu chegar em casa, irei testar a tua dica.
vlw cara, um grande abraço.
-
segunda-feira, 20 de agosto de 2012 17:09
Rui Santos, não funcionou como eu esperava. Na verdade, eu estou querendo mapear a propriedade Clientes da classe Vendedor para pegar os clientes da tabela Pedidos. No teu exemplo, ele está criando uma associacao entre as tabelas Clientes e Vendedores, e eu quero que seja com as tabelas de Vendedores e Pedidos (Muitos para muitos). Mas agradeço tua ajuda. Fico no aguardo de uma resposta sua.
vlw.
-
segunda-feira, 20 de agosto de 2012 18:56Moderador
Ola Rodrigo,
Veja bem, se for analisar o seu projeto, não faz muito sentido vc ter o Id do Vendedor na Tabela de Clientes ja que um cliente pode comprar de mais de um vendedor ...
Agora se o que voce quer é gerar uma lista de Clientes cujo um determinado vendedor atendeu, não é muito diferente do que eu apontei acima:
[Table("Clientes")] public class Cliente { [Key, Column("id")] public int ID { get; set; } [Column("Nome")] public string Nome { get; set; } } public class Vendedor { [Key, Column("id")] public int ID { get; set; } [Column("Nome")] public string Nome { get; set; } public IEnumerable<Cliente> GetClientes(DbContext context) { var query = from pedido in context.Set<Pedido>() where pedido.VendedorID == this.ID select pedido.Cliente; return query.ToArray(); } } [Table("Pedidos")] public class Pedido { [Key, Column("id")] public int ID { get; set; } [Column("Id_Vendendor")] public int VendedorID { get; set; } [Column("Id_Client")] public int ClienteID { get; set; } [ForeignKey("VendedorID")] public Vendedor Vendedor { get; set; } [ForeignKey("ClienteID")] public Cliente Cliente { get; set; } }Microsoft Community Contributor
-
segunda-feira, 20 de agosto de 2012 21:35
"Veja bem, se for analisar o seu projeto, não faz muito sentido vc ter o Id do Vendedor na Tabela de Clientes ja que um cliente pode comprar de mais de um vendedor"
É exatamente isso que você falou que estou tentando corrigir. O entity está criando o Id do Vendedor na tabela cliente, e eu estou tentando retirar essa chave estrangeira de lá.
Para resolver isso, eu tenho que mapear a propriede Clientes da classe Vendedor para a Tabela pedidos, se baseando pelo Id_Cliente e Id_Vendedor.
No Nhibernate, eu tenho algo mais ou menos assim:
public class Vendedor : Funcionario
{
[hasMany(GetType(Cliente), Table:= "Pedidos", ColumnKey:= "Id_Cliente, ComlumRef:="Id_Vendedor"]
public virtual IList<Cliente> Clientes { get; set; }
}É exatamente isso que eu quero fazer, só que com o Entity.
Eu tentei isso aqui:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Vendedor>().HasMany(v => v.Clientes).WithMany().Map(m => m.ToTable("Pedidos").MapLeftKey("Vendedor_Id").MapRightKey("Cliente_Id"));}
Porém, ele está criando duas Tabelas: Pedido e Pedido1.
A tua solução até resolve o meu problema, só que colocando o contexto como parametro para a proprieade GetClientes, perde o POCO. A minha intenção é deixar as entidades livres de tecnologias. Se eu não conseguir fazer como realmente pretendo, farei como você postou ai.
Cara, muito obrigado pela ajuda. Foi Demais.
vlw
-
terça-feira, 21 de agosto de 2012 13:54Moderador
Ah.. voce quer criar um relacionamento ternário com Code Firts....
Sinceramente confesso que não tenho a menor ideia... serio... acho q isso da tanto trabalho q eu prefiro trabalhar com 3 classes mesmo... voce pode mover a consulta para a sua classe de acesso aos dados tambem... coloquei ela na classe de mapeamento pra ficar mais facil de ilustrar apenas...
mas no mais da uma pesquisa por "EF Ternary Relationship Code First" dei uma olhada por cima mas não via grandes soluções para o seu problema... talves se procurar com calma voce encontre uma solução mais adequada.
Microsoft Community Contributor
- Marcado como Resposta RodrigoPorto segunda-feira, 27 de agosto de 2012 17:31
-
terça-feira, 21 de agosto de 2012 16:28
Rui Santos, muito obrigado pela dica e atenção. Irei aguardar um pouco mais para ver se alguem tem uma solução. Enquanto isso, vou pesquisando aqui.
vlw

