DataAnnotations - Foreign Key

08/01/2014

0

Tenho duas tabelas, que são chamadas "Unidades" e "Produtos". A chave primária na tabela Unidades chama-se "UnidadeID".
A tabela Produtos precisa duas chaves estrangeiras, nomeadas como "UnidadeDeCompra" e "UnidadeDeVenda", ambas as colunas referenciando a tabela "Unidades".
No projeto há várias outras tabelas, claro, mas com todas as demais está tudo certo. Meu problema é apenas com a "Produtos".

Ocorre que eu preciso criar o código no modelo "Entity Framework, Code First (Fluent API)" usando DataAnnotations, na linguagem VB.Net, mas especificamente para essa "dobradinha" de chaves externas, não tenho ideia de como fazer... Se fosse uma coluna de chave externa apenas, ou várias para tabelas distintas, não seria problema, mas são duas para a mesma tabela e obrigatoriamente usando os nomes citados, que não correspondem ao nome do campo na tabela referenciada... E também não posso criar via manager ou EDMX, deve ser por meio da EF6, Code First.

Alguém poderia me ajudar nesse problema?
José Santos

José Santos

Responder

Post mais votado

08/01/2014

Opa, mas é claro, desculpem!
Para exemplificar melhor o meu problema, vou usar um conceito mais fácil: Ruas e bairros, pois creio que a maioria de nós já lidou alguma vez com dados para endereçamento, ou ao menos conhece bem o que são.
Vamos dizer que para cadastrar bairros e ruas, eu, usando o Code First e o DataAnnotations, eu faça algo assim, bem simplificado:

<Table("Bairros")
Public Class Bairro
<Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)>
Public Property BairroID As Integer
<Required(ErrorMessage:="Por favor, informe o nome do bairro.")>
<StringLength(100, ErrorMessage:="O nome do bairro deve possuir até 40 caracteres.")>
Public Property Nome As String
End Class

<Table("Ruas")
Public Class Rua
<Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)>
Public Property RuaID As Integer
<Required(ErrorMessage:="Por favor, informe o nome do logradouro.")>
<StringLength(100, ErrorMessage:="O nome do logradouro deve possuir até 40 caracteres.")>
Public Property Nome As String
End Class

Com esse código, eu defini que devem ser criadas as tabelas "Ruas" e "Bairros".
Só que isso ainda não ajuda, pois é preciso relacionar ruas e bairros.
Para o nosso exemplo, digamos que será usado por uma gráfica, para imprimir um guia de mapas, não os mapas em si, mas apenas o guia.
Para essa finalidade, cada rua deve conter um campo indicando em que bairro se inicia, e outro, indicando em que bairro termina. Apenas isso.
A alteração parece simples, pois é só acrescentar esses dois campos na classe Bairro, certo? Então vamos lá:

<Table("Ruas")
Public Class Rua
<Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)>
Public Property RuaID As Integer
<Required(ErrorMessage:="Por favor, informe o nome do logradouro.")>
<StringLength(100, ErrorMessage:="O nome do logradouro deve possuir até 40 caracteres.")>
Public Property Nome As String
Public Property BairroInicialID As Integer
Public Property BairroFinalID As Integer
End Class

Mas os bairros inicial e final não foram mapeados, só existe a informação numérica por enquanto. É preciso acrescentar os campos virtuais dos bairros, o que fica assim:

<Table("Ruas")
Public Class Rua
<Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)>
Public Property RuaID As Integer
<Required(ErrorMessage:="Por favor, informe o nome do logradouro.")>
<StringLength(100, ErrorMessage:="O nome do logradouro deve possuir até 40 caracteres.")>
Public Property Nome As String
<Required()>
Public Property BairroInicialID As Integer
<Required()>
Public Property BairroFinalID As Integer
<ForeignKey("BairroInicialID")>
Public Overridable Property BairroInicial As Bairro
<ForeignKey("BairroFinalID")>
Public Overridable Property BairroFinal As Bairro
End Class

Pronto, agora sim, chegamos ao ponto onde eu estava, ou seja, no problema de encontrar o bairro quando os campos possuem nomenclatura diferente.
O que eu havia esquecido era de dizer á classe Bairro que "mapeasse" os campos vinculados das duas classes.
Para consertar a besteira, no exemplo usado aqui, bastaria fazer:

<Table("Bairros")
Public Class Bairro
<Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)>
Public Property BairroID As Integer
<Required(ErrorMessage:="Por favor, informe o nome do bairro.")>
<StringLength(100, ErrorMessage:="O nome do bairro deve possuir até 40 caracteres.")>
Public Property Nome As String
<InverseProperty("BairroInicial")>
Public Overridable Property Rua1 As Rua
<InverseProperty("BairroFinal")>
Public Overridable Property Rua2 As Rua
End Class

Com isso, a mesma tabela Bairros possui agora dois campos de chave externa com a tabela Ruas.
Em outras palavras, esquecimento puro da minha parte.
Ao menos, se isso ajudar mais alguém, já terá sido um bom trabalho ao invés de só tempo perdido.

José Santos

José Santos
Responder

Mais Posts

08/01/2014

José Santos

"Encontrei" a resposta. Na verdade, eu havia esquecido de usar o atributo "InverseProperty".
Responder

08/01/2014

Jair Souza

E como ficou esta parte do código ?
Vamos ajudar os iniciantes né.
Responder

08/01/2014

José Santos

P.S.: Usei Bairros e Ruas para simplificar, pois as classes onde estou realmente trabalhando, Unidades_De_Movimento e Produtos_Da_Loja são bem "grandinhas" e complexas, o que, creio, seria mais complicado para acompanhar.
Responder

10/01/2014

Joel Rodrigues

Obrigado por compartilhar a solução.
Tópico concluído.
Responder

Que tal ter acesso a um e-book gratuito que vai te ajudar muito nesse momento decisivo?

Ver ebook

Recomendado pra quem ainda não iniciou o estudos.

Eu quero
Ver ebook

Recomendado para quem está passando por dificuldades nessa etapa inicial

Eu quero

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar