This method works great and generates only 1 query (utilizing .Includes() to eager load).
However, I would like to refactor the AbleToDelete code to be more reusable.
(Using EF4)
public override IEnumerable<AffectProjection> SelectAll(SearchAffects page)
{
IQueryable<Affect> query = BuildSearchQuery(page);
IEnumerable<AffectProjection> results = query.Select(entity => new AffectProjection()
{
AffectID = entity.AffectID,
AffectCode = entity.AffectCode,
AffectName = entity.AffectName,
AbleToDelete = !((entity.Foo1s.Any(pa => !pa.Inactive))
|| (entity.Foo2s.Any(ea => !ea.Inactive))
|| (entity.Foo3s.Any(sa => !sa.Inactive))
|| (entity.Foo4s.Any(spa => !spa.Inactive)))
}).ToArray();
return results;
}
I moved the code into an Expression Func structure but can’t figure out how to replace my code that is setting the AbleToDelete property. Advise?
public Expression<Func<Affect, bool>> DelegateExpression = entity =>
!((entity.Foo1s.Any(pa => !pa.Inactive))
|| (entity.Foo2s.Any(ea => !ea.Inactive))
|| (entity.Foo3s.Any(sa => !sa.Inactive))
|| (entity.Foo4s.Any(spa => !spa.Inactive)));
Last but not least, this solution compiles but fails at runtime with error: “NotSupportedException – The LINQ expression node type ‘Invoke’ is not supported in LINQ to Entities.” Trying to use a delegate which isn’t supported:
public override IEnumerable<AffectProjection> SelectAll(SearchAffects page)
{
IQueryable<Affect> query = BuildSearchQuery(page);
//Create delegate instance and register method -- single statement
var deleteAbilityAllowed = new CanDelete(GetAbleToDelete);
IEnumerable<AffectProjection> results = query.Select(entity => new AffectProjection()
{
AffectID = entity.AffectID,
AffectCode = entity.AffectCode,
AffectName = entity.AffectName,
AbleToDelete = deleteAbilityAllowed(entity)
}).ToArray();
return results;
}
public delegate bool CanDelete(Affect entity);
public bool GetAbleToDelete(Affect entity)
{
return !((entity.Foo1s.Any(pa => !pa.Inactive))
|| (entity.Foo2s.Any(ea => !ea.Inactive))
|| (entity.Foo3s.Any(sa => !sa.Inactive))
|| (entity.Foo4s.Any(spa => !spa.Inactive)));
}
Please advise and thank you in advance!
LINQKit contains methods that allow you to do this. With it, you can use yout
DelegateExpression. To do that, addAsExpandable()to the source of your query and then invoke the Expression usingInvoke():Be careful though, it seems you can’t use the expression directly from the field, it has to be from a local variable.