Usuário com melhor resposta
Herança com EF4

Pergunta
-
Amigos, gostaria da ajuda de vocês para solucionar um problema que estou tendo:
Estou desenvolvendo uma aplicação com EF4 no VS2010 com SQLServer 2008, tudo funciona muito bem, menos quando trabalho com herança, tenho 3 classes, sendo Veículos, Carros e Motocicletas(nomes ficticios), obviamente Carros e Motocicletas herdam Veículos, até aí tudo bem, até o momento em que eu quero uma instância de Veículos e ele diz que Carros não está mapeado, estranho que já estava, pesquisando na internet vi a galera dizer que não se deve mapear classes filhas e utilizar um "TypeOf", mas, mapeando ou não, aparece o erro:
base {System.SystemException} = {"Object mapping could not be found for Type with identity 'Sistema.Carros'."}
estou tentando pegar uma instancia desta forma:
this.carro = contexto.Carros.Where(e => e.Codigo.Equals(codigoCarro)).Single();
alguem tem alguma idéia de algo que possa estar fazendo errado?
detalhe, as classes de dominio não estão sendo geradas pelo Visual Studio, somente o banco de dados
Fico no aguardo!
Respostas
-
Olá,
No Entity Framework, quando precisei fazer herança, após fazer o mapeamento e substituir uma associação por herança eu só conseguia fazer a consulta ao banco através da classe pai e só depois que eu convertia na classe filha:
no seu caso ficaria algo do tipo:
this.carro = contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).OfType<Carro>().FirstOrDefault();
Repare que eu faço a consulta através de veiculos (contexto.Veiculos), porém depois faço a conversão para o tipo Carro (OfType<Carro>())
Veja:
Atenciosamente
Se o post foi útil marque como resposta. - Advanced Web Application - MCP - Twitter: @mpghelli- Sugerido como Resposta AndreAlvesLimaModerator quinta-feira, 18 de novembro de 2010 17:02
- Marcado como Resposta MarkApollo quarta-feira, 24 de novembro de 2010 14:48
-
Olá Mark,
Normalmente você pode consultar através do classe pai mas não pode fazer através da classe filha, sendo necessária fazer o cast para o tipo especifico, tipo:CARRO
this.carro = contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).OfType<Carro>().FirstOrDefault();
OU
this.carro = (Carro)contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).FirstOrDefault();
MOTO
this.moto = contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).OfType<Moto>().FirstOrDefault();
OU
this.moto = (Moto)contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).FirstOrDefault();
Também deveria ser possível recuperar diretamente o veiculo sem converter para nenhum tipo:
this.veiculo = contexto.Veiculos.Where(e => e.Codigo.Equals(codigoVeiculo)).FirstOrDefault();
Mais uma dica: Normalmente no Entity Framework, uma associação que pode ser convertida em herança é um Relacionamento 1 para 1 no banco de dados. Ou seja imagina a seguinte estrutura de banco:
TABELA VEICULO TABELA CARRO TABELA MOTO
ID_VEICULO ID_VEICULO ID_VEICULORepare que eu tenho o ID_VEICULO em todas as tabelas, na tabela veiculo este campo será somente chave primária, porém na tabela carro e na tabela moto o ID_VEICULO além de chave estrangeira deve ser chave primária para que possa ser gerado um relacionamento 1 para 1.
Se você mapear estas 3 tabelas com esta estrutura pelo entity, inicialmente, será gerado uma associação, então você deve remover a associação e adionar a herança (Carro e Moto Herdam de Veiculo, ou seja, as duas "setas" geradas pelo entity para representar herança no modelo devem estar apontando para Veiculo), feito isto você deve remover o campo id_veiculo gerado no MODELO DO ENTITY para as entidades carro e moto.Espero ter ajudado
Se o post foi útil marque como resposta. - Advanced Web Application - MCP - Twitter: @mpghelli- Marcado como Resposta MarkApollo quarta-feira, 24 de novembro de 2010 14:48
-
Olá, o Entity gera através do Edmx um classe de contexto que herda de ObjectContext, este contexto contêm referência para as classes mapeadas (ObjectSet), ao fazer qualquer consulta quando se tem herança usando o Linq Por exemplo você tem que chamar o ObjectSet da classe Pai (No seu cao Veiculo) do contexto, e só depois você irá converter para o tipo desejado como por exemplo Carro ou Moto:
int codigoVeiculo = 1; Carro carro1 = (from c in contexto.Veiculos.OfType<Carro>() where c.Codigo.Equals(codigoVeiculo) select c).FirstOrDefault();
Repare que no contexto chamo veiculos e através do OfType converto para Carro.
Sempre trabalhei desta forma no EF 4 e nunca tive problema, seguia somente alguns passos com relação ao banco de dados e o mapeamento (edmx) gerado para o caso da herança:
1- O Campo Chave da Tabela Veiculo deve ser Chave Estrangeira e Chave Única nas tabelas Moto e Carro para que seja gerado um relacionamento 1 para 1
2- Ao realizar o mapeamento no entity (edmx), o modelo trará este relacionamento representado como associação, voce deve remover a associação e na toolBox do Visual Studio arrastar o componente Herança (Inheritance), onde a Classe Base será Veiculo (as setas ficarão apontando para Veiculo)
3-No modelo do entity (edmx), remova os campos chaves das Entidades Filhas (Moto e Carro)
4-Caso esteja usando algum recurso de Code Only ou Self Tracking do EF4 mande reegerar as classes das entidades.
5-Realizar as consultas , utilizando o linq por exemplo, sempre deve buscar pela classe pai no contexto (classe gerado pelo entity que herda de objectContext), depois deve realizar a conversão para o tipo desejado como já demonstrado:
int codigoVeiculo = 1; Carro carro1 = (from c in contexto.Veiculos.OfType<Carro>() where c.Codigo.Equals(codigoVeiculo) select c).FirstOrDefault();
Se nada disto funcionar é provavel que o problema esteja ou na Modelagem de Dados, ou na geração da Herança pelo modelo do Entity Framework.
Espero ter ajudado
Se o post foi útil marque como resposta. - Advanced Web Application - MCP - Twitter: @mpghelli- Marcado como Resposta MarkApollo quarta-feira, 24 de novembro de 2010 14:48
Todas as Respostas
-
Olá,
No Entity Framework, quando precisei fazer herança, após fazer o mapeamento e substituir uma associação por herança eu só conseguia fazer a consulta ao banco através da classe pai e só depois que eu convertia na classe filha:
no seu caso ficaria algo do tipo:
this.carro = contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).OfType<Carro>().FirstOrDefault();
Repare que eu faço a consulta através de veiculos (contexto.Veiculos), porém depois faço a conversão para o tipo Carro (OfType<Carro>())
Veja:
Atenciosamente
Se o post foi útil marque como resposta. - Advanced Web Application - MCP - Twitter: @mpghelli- Sugerido como Resposta AndreAlvesLimaModerator quinta-feira, 18 de novembro de 2010 17:02
- Marcado como Resposta MarkApollo quarta-feira, 24 de novembro de 2010 14:48
-
Olá, Marcus,
Depois de muitas pesquisas percebi isso também, mas, o problema é que eu não consigo fazer a consulta de um veículo simplemente, isso seria possível? ou eu terei que, obrigatóriamente, consultar sempre um carro ou uma motocicleta? na realidade, na pergunta eu coloquei o código errado, seria algo do tipo:
this.veiculo = contexto.Veiculos.Where(e => e.Codigo.Equals(codigoVeiculo)).Single();
mas, sempre dá a mensagem que coloquei lá em cima.
mas, vlw pelo link vou dar uma olhada melhor nele assim que possível.
-
Olá Mark,
Normalmente você pode consultar através do classe pai mas não pode fazer através da classe filha, sendo necessária fazer o cast para o tipo especifico, tipo:CARRO
this.carro = contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).OfType<Carro>().FirstOrDefault();
OU
this.carro = (Carro)contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).FirstOrDefault();
MOTO
this.moto = contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).OfType<Moto>().FirstOrDefault();
OU
this.moto = (Moto)contexto.Veiculos.Where(e => e.Codigo.Equals(codigoCarro)).FirstOrDefault();
Também deveria ser possível recuperar diretamente o veiculo sem converter para nenhum tipo:
this.veiculo = contexto.Veiculos.Where(e => e.Codigo.Equals(codigoVeiculo)).FirstOrDefault();
Mais uma dica: Normalmente no Entity Framework, uma associação que pode ser convertida em herança é um Relacionamento 1 para 1 no banco de dados. Ou seja imagina a seguinte estrutura de banco:
TABELA VEICULO TABELA CARRO TABELA MOTO
ID_VEICULO ID_VEICULO ID_VEICULORepare que eu tenho o ID_VEICULO em todas as tabelas, na tabela veiculo este campo será somente chave primária, porém na tabela carro e na tabela moto o ID_VEICULO além de chave estrangeira deve ser chave primária para que possa ser gerado um relacionamento 1 para 1.
Se você mapear estas 3 tabelas com esta estrutura pelo entity, inicialmente, será gerado uma associação, então você deve remover a associação e adionar a herança (Carro e Moto Herdam de Veiculo, ou seja, as duas "setas" geradas pelo entity para representar herança no modelo devem estar apontando para Veiculo), feito isto você deve remover o campo id_veiculo gerado no MODELO DO ENTITY para as entidades carro e moto.Espero ter ajudado
Se o post foi útil marque como resposta. - Advanced Web Application - MCP - Twitter: @mpghelli- Marcado como Resposta MarkApollo quarta-feira, 24 de novembro de 2010 14:48
-
Ei, Márcus, obrigado pela ajuda, mas ainda não foi, devo estar dando uma de noob,rs
Eu gerei as entidades pelo entity e mandei criar o banco, mas não busca os registros de veículos por nada, continua dando o erro
Object mapping could not be found for Type with identity 'Sistema.Carros'
Isso após eu pesquisar por Veículos.
Hoje a noite pretendo olhar melhor, tomara que consiga passar este ponto.
-
Eh, realmente ainda nada,
Refiz toda a modelagem, criei as heranças, recriei o banco, mas quando eu tento pesquisar um veiculo, ele diz que carro não está mapeado. Sempre exibindo:
Object mapping could not be found for Type with identity 'ModeloGeral.Carros'.
sendo que estou pesquisando os veículos.
Será que ninguem passou por insso ainda?
-
Olá, o Entity gera através do Edmx um classe de contexto que herda de ObjectContext, este contexto contêm referência para as classes mapeadas (ObjectSet), ao fazer qualquer consulta quando se tem herança usando o Linq Por exemplo você tem que chamar o ObjectSet da classe Pai (No seu cao Veiculo) do contexto, e só depois você irá converter para o tipo desejado como por exemplo Carro ou Moto:
int codigoVeiculo = 1; Carro carro1 = (from c in contexto.Veiculos.OfType<Carro>() where c.Codigo.Equals(codigoVeiculo) select c).FirstOrDefault();
Repare que no contexto chamo veiculos e através do OfType converto para Carro.
Sempre trabalhei desta forma no EF 4 e nunca tive problema, seguia somente alguns passos com relação ao banco de dados e o mapeamento (edmx) gerado para o caso da herança:
1- O Campo Chave da Tabela Veiculo deve ser Chave Estrangeira e Chave Única nas tabelas Moto e Carro para que seja gerado um relacionamento 1 para 1
2- Ao realizar o mapeamento no entity (edmx), o modelo trará este relacionamento representado como associação, voce deve remover a associação e na toolBox do Visual Studio arrastar o componente Herança (Inheritance), onde a Classe Base será Veiculo (as setas ficarão apontando para Veiculo)
3-No modelo do entity (edmx), remova os campos chaves das Entidades Filhas (Moto e Carro)
4-Caso esteja usando algum recurso de Code Only ou Self Tracking do EF4 mande reegerar as classes das entidades.
5-Realizar as consultas , utilizando o linq por exemplo, sempre deve buscar pela classe pai no contexto (classe gerado pelo entity que herda de objectContext), depois deve realizar a conversão para o tipo desejado como já demonstrado:
int codigoVeiculo = 1; Carro carro1 = (from c in contexto.Veiculos.OfType<Carro>() where c.Codigo.Equals(codigoVeiculo) select c).FirstOrDefault();
Se nada disto funcionar é provavel que o problema esteja ou na Modelagem de Dados, ou na geração da Herança pelo modelo do Entity Framework.
Espero ter ajudado
Se o post foi útil marque como resposta. - Advanced Web Application - MCP - Twitter: @mpghelli- Marcado como Resposta MarkApollo quarta-feira, 24 de novembro de 2010 14:48
-
Marcus, Olá novamente, rapaz, tem algo de muito errado na minha aplicação, já refiz o modelo e nada, e já estava fazendo justamente como vc está dizendo!
decidi por não trabalhar com herança por agora, já que, neste momento é um "simples" trabalho de faculdade, mas logo após vou correr atraz do problema.
vlw pela ajuda!
-
Olá Pessoal,
Muito Obrigado pela ajuda! Vou tentar implementar e ver como fica. Caso dê muito trabalho acho que vou fazer como o Mark disse e daí quando foi gerar um novo mapeamento que não haja tabelas aí sim vou explorar mais essa parte!
Abraços