I am writing a database query using LINQ in .NET and I want to be able to not duplicate the code I put in my Where method calls. All my entities inherit BaseEntity and have in common the properties used in the Where call.
public class BaseEntity
{
public Guid Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public DateTime? DeletedAt { get; set; }
}
public class A : BaseEntity
{
public List<B> Bs { get; set; }
}
public class B : BaseEntity
{
public A A { get; set; }
}
At the moment I have written a query that works but I am not satisfied that I need to duplicate code. It looks like this:
var result = _context.Set<A>().Include(a => a.Bs.Where(b => b.DeletedAt == null && b.UpdatedAt > dateTime ||
b.DeletedAt != null && b.DeletedAt > dateTime))
.Where(a => a.DeletedAt == null && a.UpdatedAt > dateTime ||
a.DeletedAt != null && a.DeletedAt > dateTime)
.ToList();
As you can see the code in Where calls is pretty much the same, yet I couldn't find a way to put it in a place and be able to reuse it. I did try to create an extension for IQueryable but I wouldn't be able to use it in the Where inside the Include becuause Bs is not IQueryable.
Obviously, just putting the logic in a method doesn't work because it can't be translated.
a.Bs.Where(...)it actually expects aFunc, not anExpression. Yet, if i just put aFuncin a variable and then use it, it wouldn't be able to translate the query.Wherein theIncludeworks and it is also necessary. I just need a way to reuse that statement as it will appear in many places and I don't want to have to copy it all over the place.Expression<Func<BaseEntity, Bool>>, pass it unchanged in the second position, and for the first position synthesize an appropriateExpression<Func<A, List<B>>>using the tools described here and theExpression<Func<BaseEntity, Bool>>you factored out.