Como você lança uma tabela Linqtosql como uma mesa Onde a tentativa: iEntity?
-
26-09-2019 - |
Pergunta
Estou tentando usar o dblinq com um banco de dados sqlite, mas estou tendo um problema quando tento lançar um ITable
como um Queryable<TEntity>
.
Há um bug conhecido no dblinq (Edição 211), qual pode ser a fonte do meu problema, mas eu queria garantir que meu código seja sólido e, se for, descubra se pode haver algo que eu possa fazer para contornar o bug.
Aqui está o método de repositório genérico que tenta fazer o elenco:
public IQueryable<TEntity> GetAll()
{
return Table.Cast<TEntity>(); // Table is an ITable
}
Isso compila, mas se eu passar na interface IPerson
por TEntity
e o tipo de entidades na tabela é Person
(Onde Person : IPerson
), Estou recebendo esse erro do dblinq:
S0133: Implementar querymethod queryable.cast.
Por que estou tentando fazer isso?
Eu tenho um projeto de biblioteca que não conhece o tipo de entidade até o tempo de execução, mas ele conhece a interface da entidade. Então, estou tentando lançar para o tipo de interface para que meu projeto de biblioteca possa consumir os dados.
Perguntas:
- Estou tentando um elenco impossível ou isso é definitivamente um bug no dblinq?
- De que outra forma eu poderia resolver meu problema?
Atualizar
Eu reformulei minha aula de repositório para que agora seja necessário um TEntity
e uma TEntityBase
, Onde TEntity
é o tipo real da entidade, e TEntityBase
é a interface que estou tentando lançar. Importante, agora tenho o seguinte where
Cláusula na minha definição de classe:
where TEntity : class, TEntityBase
Isso me permite armazenar meu Table
propriedade como a Table<TEntity>
em vez de um ITable
, o que me permite usar AsEnumerable()
(como Stephen sugeriu). Aqui está o método revisado:
public IEnumerable<TEntityBase> GetAll()
{
return Table.AsEnumerable().Select(e => (TEntityBase)e);
}
E até agora, que parece Para fazer o truque.
Solução
Parece um bug, mas entenda que a implementação de um provedor LINQ é um empreendimento absolutamente enorme. Mesmo (da Microsoft) LINQ para SQL e LINQ para entidades têm suas próprias restrições sobre exatamente quais consultas/operações do LINQ eles suportam ou não suportam.
Se retornar IEnumerable<T>
é aceitável, então você pode contornar a falta de apoio para Queryable.Cast
ligando AsEnumerable
antes de ligar Cast
. No entanto, isso restringe como seu dal pode ser usado: uma vez IQueryable<T>
não é mais devolvido, outras consultas (por exemplo, Where
cláusulas) não serão passadas para a camada de banco de dados.
Outras dicas
Eu concordo que parece um bug. Você pode tentar o seguinte que fará a mesma coisa
return Table.Select<TEntity>(tbl => (TEntity)tbl)
Você pode precisar adicionar um lugar: Itable à definição de método também.