Subtleties of Lambda Expressions in C #
What I wrote in the article, I caught about 10 hours, it was 10 hours of continuous debug that reduced to a step-by-step comparison of the working and non-working versions of the code, not even that, to comparing each line from the debug window of the working and non-working versions of the code
For a programmer who is not familiar with expression trees, a good introductory article on msdn reveals in detail some steps in building a tree that I omitted in the article.
In which case this test will be green (the EF add-in is enabled, in which it crashes if it cannot fully translate the query into SQL ).
- First, the mapping of the PupilName field must be defined if it is not defined. The Query Provider does not recognize what the PupilName property needs to be projected on in order to append to SQL ORDER BY .
Secondly, the provider must parse this mapping, for example, it will not work, EF will start swearing (by default it does not swear, it raises entities in memory - LINQ to Object , but this can be enabled ):
And the thing is that the Query Provider does not understand by what property (s) of the entity we want to sort. But if the mapping is written correctly, then the provider will cope, send an SQL query, receive a response and deserialize the results.
Sometimes it becomes necessary to write Expressions yourself, i.e. something similar:
I’ll show you how to write this Expression , it’s not so difficult, the link above provides several similar examples:
We collect the lambda step by step, first a parameter, a property, and then glue everything.
In which case this will not work and the test will be green (the provider will not be able to parse expression)?
Do not know? Don’t worry, I didn’t know either, and in the end I spent about 10 hours to understand.
Here is a hint, this will work:
The thing is that PropertyInfo needs to be taken from the base class if the PupilName property itself belongs to the base class, so C # builds lambda expression , and EF parses them, relying on language standards
What debugger shows if you write a regular lambda in OrderBy :
And in our case, like this:
AutoMapper and IncludeBase
If you try not to duplicate the code, then you probably came across the inheritance of DTO and IncludeBase :
There is an even more sophisticated situation:
And this test will be green:
And the thing is the same, again PropertyInfo is pulled from the interface:
The ReflectedType of the Age property is an interface, IPupilDto , C # builds a lambda, in which the Age property is a property of the PupilDto class, not the interface, but here's how the automapper builds a lambda:
How to solve this problem? If IncludeBase Automapper with an interface does not suit us (if you use mapping in memory - it will not affect you), then you will have to abandon this API, I solved this problem by highlighting mapping in the extension method , like this:
Then the auto-mapper itself will find a suitable type property by name, build a "correct" lambda
Thank you for your attention!