I have some complex LinQ queries having sets of similar complex expressions:
IEnumerable<MyEntity> MyRepoMt1()
{
return _myContext.MyEntities.Where(<several rules A>> && different stuff) .ToList() ;
}
IEnumerable<MyEntity> MyRepoMt2()
{
return _myContext.MyEntities.Where(<several rules A>> && different stuff) .ToList(); // Same rules A than previous method
}
…
IEnumerable<MyEntity> MyRepoMt3()
{
return _myContext.MyEntities.Where(<several rules B> > && different stuff) .ToList();
}
IEnumerable<MyEntity> MyRepoMt4()
{
return _myContext.MyEntities.Where(<several rules B> && different stuff) .ToList(); // Same rules B than previous method
}
IEnumerable<MyEntity> MyRepoMt5()
{
return _myContext.MyEntities.Where(<several rules A> || <several rules B>) .ToList(); // Same rules A and B than previous method
}
…
I would like to refactor and in the best possible way. My first attempt was as follows, using a method returning a bool:
Bool CheckRulesA(MyEntity e){ …}
Bool CheckRulesB(MyEntity e){ …}
I called it this way:
IEnumerable<MyEntity> MyRepoMt1()
{
return _myContext.MyEntities.Where(e => CheckRulesA( e) && different stuff) .ToList() ;
}
It failed because EF could not execute CheckRulesA on server side and threw an exception.
I changed it to a method dealing with IQueryable :
IQueryable<MyEntity> CheckRulesA(IQueryable<MyEntity> query)
{
Return query .Where(e => …..).ToList() ;
}
This solved my previous issue. I can do :
IEnumerable<MyEntity> MyRepoMt1()
{
return CheckRulesA(_myContext.MyEntities).Where(different stuff…).ToList() ;
}
I could enhance it with an extension method but it s not my point right now.
But it is not fully acceptable as it does not handle cases with || operators (My last MyRepoMt5() example).
In this last scenario, I need to return entities that check RulesA OR RulesB. I don’t want to do something as ugly as
Var q2 = (CheckRulesA(_myContext.MyEntities) || CheckRulesB(_myContext.MyEntities)).Distinct();
This looks terribly awful to me.
How am I to handle this properly ?