Há um tipo de entidade chamado produto que é gerado pela estrutura da entidade. Escrevi esta consulta
public IQueryable<Product> GetProducts(int categoryID)
{
return from p in db.Products
where p.CategoryID== categoryID
select new Product { Name = p.Name};
}
O código abaixo gera o seguinte erro:
"A entidade ou o tipo complexo Shop.Product não pode ser construído em uma consulta LINQ to Entities"
var products = productRepository.GetProducts(1).Tolist();
Mas quando eu uso, em select p
vez disso select new Product { Name = p.Name};
, funciona corretamente.
Como posso pré-formar uma seção de seleção personalizada?
c#
entity-framework
Ghooti Farangi
fonte
fonte
Respostas:
Você não pode (e não deve ser capaz de) projetar em uma entidade mapeada. No entanto, você pode projetar em um tipo anônimo ou em um DTO :
E seu método retornará uma lista de DTOs.
fonte
Você pode projetar em tipo anônimo e, a partir dele, em modelo
Edit : Eu vou ser um pouco mais específico, pois esta pergunta recebeu muita atenção.
Você não pode projetar diretamente no tipo de modelo (restrição EF); portanto, não há como contornar isso. A única maneira é projetar em tipo anônimo (1ª iteração) e depois em tipo de modelo (2ª iteração).
Lembre-se também de que, quando você carrega parcialmente entidades dessa maneira, elas não podem ser atualizadas; portanto, devem permanecer desanexadas como estão.
Eu nunca entendi completamente por que isso não é possível, e as respostas neste segmento não dão razões fortes contra isso (principalmente falando sobre dados parcialmente carregados). É correto que a entidade no estado parcialmente carregado não possa ser atualizada, mas essa entidade seria desanexada, portanto, tentativas acidentais de salvá-las não seriam possíveis.
Considere o método que usei acima: ainda temos uma entidade de modelo parcialmente carregada como resultado. Esta entidade está desanexada.
Considere este código possível (desejo de existir):
Isso também pode resultar em uma lista de entidades desanexadas, portanto, não precisamos fazer duas iterações. Um compilador seria esperto ao ver que AsNoTracking () foi usado, o que resultará em entidades desanexadas, para que isso nos permita fazer isso. Se, no entanto, AsNoTracking () for omitido, poderá lançar a mesma exceção que está lançando agora, para nos alertar que precisamos ser específicos o suficiente sobre o resultado que queremos.
fonte
Há outra maneira que eu achei que funciona: você precisa criar uma classe que deriva da sua classe Product e usá-la. Por exemplo:
Não tenho certeza se isso é "permitido", mas funciona.
fonte
Aqui está uma maneira de fazer isso sem declarar classe adicional:
No entanto, isso só deve ser usado se você deseja combinar várias entidades em uma única entidade. A funcionalidade acima (mapeamento simples de produto para produto) é feita assim:
fonte
Outra maneira simples :)
fonte
.ToList
consulta, ela é executada e extraída de dados do servidor, qual é o objetivo de fazê-la novamenteAsQueryable
?Você pode usar isso e ele deve estar funcionando -> Você deve usar
toList
antes de fazer a nova lista usando select:fonte
Em resposta à outra pergunta que foi marcada como duplicada ( veja aqui ), descobri uma solução rápida e fácil com base na resposta de Soren:
Nota: Esta solução funciona apenas se você tiver uma propriedade de navegação (chave estrangeira) na classe Task (aqui chamada 'Incidente'). Se você não tiver, basta usar uma das outras soluções publicadas com "AsQueryable ()".
fonte
Você pode resolver isso usando objetos de transferência de dados (DTO).
Estes são um pouco como os modelos de visualização em que você coloca as propriedades necessárias e pode mapeá-las manualmente em seu controlador ou usando soluções de terceiros como o AutoMapper.
Com os DTOs, você pode:
Aprendi isso na escola este ano e é uma ferramenta muito útil.
fonte
Se você estiver usando a estrutura da Entidade, tente remover a propriedade do DbContext que usa seu modelo complexo como Entidade. Eu tive o mesmo problema ao mapear vários modelos em um modelo de exibição chamado Entidade
A remoção da entrada do DbContext corrigiu meu erro.
fonte
se você estiver executando,
Linq to Entity
não poderá usáClassType
-lonew
noselect
fechamento da consultaonly anonymous types are allowed (new without type)
dê uma olhada neste trecho do meu projeto
de você adicionou o
new keyword
fechamento no Select, mesmo no casocomplex properties
deste erroporque ele será transformado em instrução sql e executado no SqlServer
então quando posso usar
new with types
noselect
fechamento?você pode usá-lo se estiver lidando com
LINQ to Object (in memory collection)
depois que eu executei
ToList
na consulta, tornou-sein memory collection
para que possamos usarnew ClassTypes
em selectfonte
Em muitos casos, a transformação não é necessária. Pense no motivo pelo qual você deseja o tipo forte List e avalie se deseja apenas os dados, por exemplo, em um serviço da Web ou para exibi-lo. Não importa o tipo. Você só precisa saber como lê-lo e verificar se é idêntico às propriedades definidas no tipo anônimo que você definiu. Esse é o cenário otimizado, causa algo que você não precisa em todos os campos de uma entidade e é por isso que o tipo anônimo existe.
Uma maneira simples é fazer isso:
fonte
Não permitirá que você mapeie de volta para o produto, pois essa é a sua tabela que você está consultando. Você precisa de uma função anônima, pode adicioná-la a um ViewModel e adicionar cada ViewModel a
List<MyViewModel>
e retorná-las. É uma ligeira digressão, mas eu incluo advertências sobre como lidar com datas anuláveis, porque essas são uma dor nas costas por trás, para o caso de você ter alguma. É assim que eu lidei com isso.Espero que você tenha um
ProductViewModel
:Eu tenho uma estrutura de injeção / repositório de dependência onde chamo uma função para capturar meus dados. Usando sua postagem como exemplo, na sua chamada de função Controller, ficaria assim:
Na classe do repositório:
De volta ao controlador, você faz:
fonte
adicione apenas AsEnumerable ():
fonte
você pode adicionar AsEnumerable à sua coleção da seguinte maneira:
fonte