I am attempting to build a lambda from data.
The module entity has an AlgNo property of type string. I am trying to get a simple sample code to run before attempting the more advanced case.
Consider two entities "Composition" and "Module". Composition has multiple modules. When I retrieve compositions from the database, I want to only load the moduletypes that are relevant for the use case. Loading all modules for every composition would take a lot of memory. Eg. If composition if of type "A", I want to load modules with AlgNo equaling "25","51" or "53". So the hard coded case would be.
EF_Repo.Compositions.Where( <some clause)
.Include ( comp => comp.Modules.Where( m=> (m.Composition == "A" && new[]{"25","51", "53"}.Contains(m.AlgNo)))
|| ((m.Composition == "B" && new[] {"15","21"}.Contains(m.AlgNo)))));
This generates the proper SQL to filter server side. However, The exact modules for each composition type are represented in the domain model, so I hope to generate the predicate from code.
(Please ignore that "AlgNo" is a string type.)
In order to get there, I want to start with the simple case of creating a Expression<Func<Module,bool>>. I do this by running the two variations side by side in LINQPad and instecting the resulting Expression tree. However, I am getting an error message. "InvalidOperationException: The LINQ expression 'm' could not be translated."
void Main()
{
Modules.Where(CreateLambda()).Take (100).Dump();
//Modules.Where(m=>m.AlgNo=="48").Take (100).Dump();
}
Expression<Func<LINQPad.User.Module,bool>> CreateLambda()
{
var modpar = Expression.Parameter(typeof(LINQPad.User.Module),"m");
var algnoProp = typeof(LINQPad.User.Module).GetProperty(nameof(LINQPad.User.Module.AlgNo));
var algnoaccessor = Expression.Property(modpar,algnoProp);
var ma = Expression.MakeMemberAccess(modpar,algnoProp);
var no48 = Expression.Constant("48");
var equality = Expression.Equal(no48,ma);
var lambda = Expression.Lambda<Func<LINQPad.User.Module,bool>>(equality,false,Expression.Parameter(typeof(LINQPad.User.Module),"m"));
return lambda;
}
I an struggling on how to use the various factory methods found at "Expression." to generate the structure that the compiler generates autaomatically when passing in the labmda expression.
Expression.Lambdaexpectsbody(which in your case is theequalityvariable) andparameters(which in your case is singlemodparvariable), so the call should beExpression.Lambda<Func<LINQPad.User.Module,bool>>(equality, modpar)