shapper said:
[...]
I understand the second suggestion Jeroen gave but I can't understand
why the first one gives me the error.
As I wrote before, it's a basic requirement of how LINQ to SQL works.
LINQ to SQL is translating your lambda expressions into SQL. This means
two things (at least):
-- It has to be a single expression, because the translation to SQL
is done via expression trees; a lambda that can't be converted to an
expression tree can't be used in LINQ to SQL
-- The expression has to be able to be rewritten as SQL
Your attempt to use a lambda statement body fails to meet the first
requirement. Even if C# allowed you to skip the first requirement, no
doubt it would fail to meet the second requirement. SQL has no
knowledge of your C# objects, such as whatever type the "ml" winds up being.
And I can't understand what other information I am missing to help in
solving that problem.
Solving what problem? Understanding why it won't work? Or getting it
to work? If the latter, then there is no amount of information you can
provide that will help solve that problem. There's no solution to that
problem. It simply cannot work that way.
If the former, the information you need to provide has nothing to do
with your code. Rather, for a better explanation to be provided, you
need to explain what it is about the explanations given so far that you
are having difficulty understanding.
return _context.Messages.Select(m => {
var ml = m.MessageLocalized.FirstOrDefault(l => l.Language.Code==
languageCode);
return new MessageModel {
Id = m.Id,
Name = m.Name,
Language = languageCode,
Content = ml.Content,
Title = ml.Title
}
});
IList<MessageModels> result = new List<MessageModel>();
foreach (Message m in _context.Messages) {
var ml = m.MessageLocalized.FirstOrDefault(l => l.Language.Code==
languageCode);
result.Add(new MessageModel {
Id = m.Id,
Name = m.Name,
Language = languageCode,
Content = ml.Content,
Title = ml.Title
}
}
return result;
That is an incorrect interpretation. In particular, LINQ in general
(and in this specific instance) does NOT actually execute a query or
enumeration until necessary. The thing that is returned in your first
example is the wrapper that, when eventually used, will retrieve the
data needed. The thing that is returned in your second example is
completely different, being the product of the actual work to do the
enumeration.
The other problem with your interpretation is that, even if the first
example did actually do the enumeration before returning from the
method, there's absolutely no way for the compiler to move the "ml = "
assignment out of the lambda. The lambda is an object unto itself and
having been passed to some other method, can be used at any time in any
way. Everything that is in the lambda as written in the code MUST
remain in the lambda, and that includes any local variables and their
initialization that are in the body of the lambda.
So the part inside m => { is running the code inside the foreach loop
for each m.
But I don't understand why do I get the error and how can I solve it:
"A lambda expression with a statement body cannot be converted to an
expression tree"
You can solve that error by writing the code as the second example
Jeroen provided (which is basically the same as the one Martin provided
from the outset).
Pete