Today I have this repeated code:
public class MyProjectionExpressions
{
public static Expression<Func<Log, dynamic>> LogSelector()
{
return log => new
{
logId = log.LogId,
message = log.Message,
};
}
public static dynamic LogSelector(Log log)
{
return new
{
logId = log.LogId,
message = log.Message,
};
}
}
The first method is a reusable projection expression, which I use like this:
db.Logs.Select(MyProjectionExpressions.LogSelector());
The second method is used when I'm not dealing with collections, but just one item that needs to be serialized, like this:
MyProjectionExpressions.LogSelector(someLog);
I tried reusing code, like this:
public class MyProjectionExpressions
{
public static Expression<Func<Log, dynamic>> LogSelector()
{
return log => MyProjectionExpressions.LogSelector(log);
}
public static dynamic LogSelector(Log log)
{
return new
{
logId = log.LogId,
message = log.Message,
};
}
}
But then, I had the "Linq-To-Entities vs Linq-To-Objects" problem, that is: I would have to reuse my projection expression like this:
db.Logs.ToList().Select(MyProjectionExpressions.LogSelector());
Because MyProjectionExpressions.LogSelector() now contains (uses) a method that is not recognized by Linq-To-Entities:
LINQ to Entities does not recognize the method 'MyProjectionExpressions.LogSelector()'
Question is, finally:
how can I reuse the lamba expression in a way that Linq-To-Entities continues to work?
This lambda expression:
log => new
{
logId = log.LogId,
message = log.Message,
};
dynamichere. You should be creating a new named type. Not only will performance improve dramatically due to not needing to be compiling the code to execute this at runtime, but you'll add static type safety and ensure that the compiler can catch any errors in your use of this type's members. It's well worth the 30 seconds it'd take to create a named type with these two properties.