ENTITYFRAMEWORK - FOREIGNKEY

DS2T 15/06/2016 05:46:47
#463532
Olá, bom dia a todos!

Sou novo com o Entity Framework e estou com algumas dúvidas.

A primeira: Existe uma forma de carregar o objeto com todas os seus filhos já carregados automaticamente?

Quando eu uso o método Find do DbSet, ele não carrega os filhos, só os dados da classe pai.
Eu até consegui fazer usando o método Include, assim:

        Public Function RetornaRotaComDependentes(id As Integer) As Rota
Dim r As Rota
Using dao As New Contexto
Dim query As DbQuery(Of Rota) = From rotas In dao.Rotas Where rotas.Id = id
query = query.Include([Ô]RotasFretes[Ô])

Dim subQuery As DbQuery(Of NotaFiscalEletronica) = From notas In dao.NotasFiscais Where notas.RotaId = id
subQuery = subQuery.Include([Ô]Emitente[Ô]).Include([Ô]Destinatario[Ô]).Include([Ô]Produtos[Ô])

r = query.FirstOrDefault
r.NotasFiscais = subQuery.ToList()
End Using

Return r
End Function


Mas sinceramente? é muito trabalho para coisa tão pouco.
Acredito que o Entity deve ter algo mais simples, nesse sentido. Caso contrário, terei que usar Reflection pra facilitar as coisas.


Segunda coisa: Em relação a editar os objetos que possuem filhos. Sério mesmo que preciso fazer na munheca a verificação do filho que foi apagado ou adicionado?!
Encontrei esse exemplo:

http://www.entityframeworktutorial.net/EntityFramework4.3/update-one-to-many-entity-using-dbcontext.aspx

Achei bizarro demais. O Entity não possui algo automático nesse sentido?

Estou fazendo essas perguntas... Só pra desencargo de consciência. Porque pelo visto, terei que apelar pro Reflection mesmo...

Abraços!
JABA 15/06/2016 17:26:12
#463572
Resposta escolhida
DS2T, esse processo é conhecido como Lazy Loading e Eager Loading. E pelo o que eu saiba, se você estiver desenvolvendo pelo Code First, o Entity Framework já faz esse trabalho automaticamente. Se você quiser que ele preencha de forma tardia, é só declarar as propriedades como Virtual(c#) ou Overridable(Vb.net). Assim, os filhos só serão carregados quando forem chamados.
KERPLUNK 15/06/2016 19:27:16
#463573
é o que o JABA disse, esse comportamento pode ser modificado:

MeuContexto db = new MeuContexto();
db.Configuration.LazyLoadingEnabled = false;
DS2T 16/06/2016 02:58:36
#463590
Primeiramente, brigadão pelas informações. Bem útil.

Acontece que estou desenvolvendo usando o DataAnnotations.
Deixei minha lista como Overridable, mas acontece o seguinte erro:

[ô]DirectCast(r, System.Data.Entity.DynamicProxies.Rota_52EB46CDE17BB3B52D3710D28B86FC97761B785B6FD7AAE070EA52D1697E9FD3).RotasFretes[ô] threw an exception of type [ô]System.ObjectDisposedException[ô]


A estrutura está assim:

<Table([Ô]rotas[Ô])>
Public Class Rota
Implements IUniqueID

<Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)>
Public Property Id As Nullable(Of Int32) Implements IUniqueID.Id

Public Overridable Property RotasFretes As New List(Of FreteRota)

End Class



    <Table([Ô]fretes_rotas[Ô])>
Public Class FreteRota
Implements IUniqueID
<Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)>
Public Property Id As Nullable(Of Integer) Implements IUniqueID.Id

<Column([Ô]rota_id[Ô])>
Public Property RotaId As Integer

<ForeignKey([Ô]RotaId[Ô])>
Public Property Rota As Rota

End Class



Mas quando uso o método Find para retornar o objeto pelo Id, as listas aparecem com o erro já exposto acima.

Alguma idéia?

Muito obrigado!
JABA 16/06/2016 16:16:55
#463638
Tente assim:
Public Overridable Property RotasFretes () As ICollection(Of FreteRota)


Citação:

Public Property Id As Nullable(Of Integer)



Por que você colocou a id podendo receber nulos? Ela pode ir assim para o banco?

DS2T 19/06/2016 04:25:19
#463779
Fala aí Jaba! Desculpa a demora pelo retorno, depois de muito tempo, minha vida anda um pouco sobrecarregada.

Citação:

Por que você colocou a id podendo receber nulos? Ela pode ir assim para o banco?


é que quando eu adiciono, o ID fica nulo. Porque ele é de auto-numeração.

Fiz como você sugeriu:

        Public Overridable Property RotasFretes As ICollection(Of FreteRota)



Quando tento indicar ele com o LazyLoadingEnabled = True e acesso a propriedade, fica perfeito.
Ele retorna tudo preenchido.

Só que na hora de tentar usar o Eager Loading (LazyLoadingEnabled = False), a coleção vem como Nothing. Aí tentei tirar a keyword Overridable na propriedade, mas também não funcionou. Vem sempre como Nothing.


Alguma ideia do que possa ser?

(Minha namorada do video, manda lembranças!)
JABA 19/06/2016 14:55:26
#463785
Você já experimentou colocar o LazyLoadingEnabled = True e retirar a keyword Overridable ? Testa aí e vê se funciona.

Citação:

(Minha namorada do video, manda lembranças!)



Poxa cara, que bom que deu certo entre vocês! Confesso que estou com uma tremenda inveja. Talvez em outra vida, eu dê uma sorte dessas. hehe
DS2T 29/06/2016 22:09:04
#464315
Oi Jaba, boa noite!

Desculpa de novo a demora, desde aquele dia não mexi no projeto. Aí peguei hoje pra realizar os testes.

Tentei colocar LazyLoadingEnabled = True, com propriedade Overridable e sem Overridable. Nenhum deles consegui preencher o filho, sem uma chamada da propriedade antes.
Tentei colocar LazyLoadingEnabled = False, com e sem Overridable. Também nada.

Agora estou dando uma pesquisada de novo, qualquer coisa eu posto aqui.

Valeu!
DS2T 29/06/2016 22:41:01
#464317
Então, pelo que li, parece que precisarei usar o Include mesmo.
Segue alguns posts de referência:

http://www.entityframeworktutorial.net/EntityFramework4.3/eager-loading-with-dbcontext.aspx
http://stackoverflow.com/questions/14512285/entity-framework-is-there-a-way-to-automatically-eager-load-child-entities-wit

Confere?
JABA 30/06/2016 00:30:23
#464320
Sim, é isso mesmo.

https://ferhenriquef.com/2012/03/19/uso-de-include-em-consultas-com-o-entity-framework-code-first/
DS2T 02/07/2016 13:55:20
#464431
A última questão, prometo hahahaha

O meu primeiro código estava assim:

Public Function RetornaRotaComDependentes(id As Integer) As Rota
Dim r As Rota
Using dao As New Contexto
Dim query As DbQuery(Of Rota) = From rotas In dao.Rotas Where rotas.Id = id
query = query.Include([Ô]RotasFretes[Ô])

Dim subQuery As DbQuery(Of NotaFiscalEletronica) = From notas In dao.NotasFiscais Where notas.RotaId = id
subQuery = subQuery.Include([Ô]Emitente[Ô]).Include([Ô]Destinatario[Ô]).Include([Ô]Produtos[Ô])

r = query.FirstOrDefault
r.NotasFiscais = subQuery.ToList()
End Using

Return r
End Function



Consegui passar ele para isso:

  Public Function RetornaRotaComDependentes(id As Integer) As Rota
Dim r As Rota

Using dao As New Contexto
Dim q As IQueryable(Of Rota) = From rota In dao.Rotas Where rota.Id = id

q = q.Include(Function(x) x.NotasFiscais.Select(Function(k) k.Produtos)).
Include(Function(y) y.RotasFretes).
Include(Function(p) p.NotasFiscais.Select(Function(z) z.Emitente)).
Include(Function(p) p.NotasFiscais.Select(Function(d) d.Destinatario))

r = q.FirstOrDefault()

End Using

Return r
End Function



Existe um código ainda menor do que esse?
Ou esse é a otimização máxima?

Valeu novamente!
Página 1 de 2 [13 registro(s)]
Tópico encerrado , respostas não são mais permitidas