Sutilezas de expressões lambda em c #

O que escrevi no artigo, peguei cerca de 10 horas, foram 10 horas de depuração contínua, o que reduziu a uma comparação passo a passo das versões de trabalho e não-trabalho do código, nem mesmo isso, para comparar cada linha da janela de depuração das versões de trabalho e não-trabalho do código


Para um programador que não está familiarizado com as árvores de expressão, um bom artigo introdutório sobre o msdn revela em detalhes algumas etapas na construção de uma árvore que eu omiti no artigo.


Nesse caso, esse teste ficará verde (o suplemento EF está ativado, no qual ele falha se não conseguir converter completamente a consulta em SQL ).



  • Primeiro, o mapeamento do campo PupilName deve ser definido se ele não estiver definido.O Query Provider não reconhece o que a propriedade PupilName precisa ser projetada para anexar ao SQL ORDER BY .
  • Em segundo lugar, o provedor deve analisar esse mapeamento, por exemplo, ele não funcionará, o EF começará a xingar (por padrão, não jura, gera entidades na memória - LINQ to Object , mas isso pode ser ativado ):




E o fato é que o provedor de consultas não entende por quais propriedades da entidade que queremos classificar. Mas se o mapeamento for escrito corretamente, o provedor irá lidar, enviar uma consulta SQL , receber uma resposta e desserializar os resultados.


Às vezes, torna-se necessário escrever Expressões você mesmo, ou seja, algo semelhante:



Vou mostrar como escrever essa expressão , não é tão difícil, o link acima fornece vários exemplos semelhantes:



Coletamos o lambda passo a passo, primeiro um parâmetro, uma propriedade e, em seguida, colamos tudo.
Nesse caso, isso não funcionará e o teste ficará verde (o provedor não poderá analisar a expressão)?


Não sabe? Não se preocupe, eu também não sabia e, no final, passei cerca de 10 horas para entender.
Aqui está uma dica, isso funcionará:



O PupilDto herda do PupilDtoBase


O problema é que PropertyInfo precisa ser retirado da classe base se a própria propriedade PupilName pertencer à classe base, então o C # cria a expressão lambda e o EF as analisa, baseando-se nos padrões de linguagem


Provas

O depurador mostra se você escreve um lambda regular no OrderBy :



E no nosso caso, assim:



AutoMapper e IncludeBase


Se você tentar não duplicar o código, provavelmente encontrará a herança do DTO e do IncludeBase :



Há uma situação ainda mais sofisticada:



E este teste será verde:



E a coisa é a mesma, novamente PropertyInfo é extraído da interface:



Provas

A propriedade ReflectedType of the Age é uma interface, IPupilDto , C # constrói um lambda, na qual a propriedade Age é uma propriedade da classe PupilDto, não a interface, mas aqui está como o automapper cria um lambda:



Como resolver este problema? Se o IncludeBase Automapper com uma interface não se adequar a nós (se você usar o mapeamento na memória - isso não o afetará), será necessário abandonar esta API. Resolvi esse problema destacando o mapeamento no método de extensão , desta forma:



Em seguida, o próprio mapeador automático encontrará uma propriedade de tipo adequada por nome, crie o lambda "correto"
Obrigado pela atenção!

Source: https://habr.com/ru/post/pt453720/


All Articles