我正在 .NET 中使用 LINQ 编写数据库查询,并且我希望能够不重复我在
Where
方法调用中放入的代码。我的所有实体都继承 BaseEntity
并具有在 Where
调用中使用的共同属性。
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; }
}
目前我已经编写了一个有效的查询,但我不满意需要重复代码。看起来像这样:
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();
正如您所看到的
Where
调用中的代码几乎相同,但我找不到一种方法将其放在某个位置并能够重用它。我确实尝试为 IQueryable
创建扩展,但我无法在 Where
内的 Include
中使用它,因为 Bs
不是 IQueryable
。
显然,仅仅将逻辑放入方法中是行不通的,因为它无法被翻译。
一个常见的表达方式应该有效,但它可能没有正确实现,因为它们可能有点喜怒无常。例如:
private Expression<Func<T, bool>> FilterByDate<T>(DateTime dateTime) where T : BaseEntity
{
Expression<Func<T, bool>> expression = x =>
(x.DeletedAt == null && x.UpdatedAt > dateTime)
|| (x.DeletedAt != null && x.DeletedAt > dateTime)
return expression;
}
然后在您的查询中:
var result = _context.Set<A>().Include(a => a.Bs.Where(filterByDate<B>(dateTime))
.Where(a => filterByDate<A>(dateTime))
.ToList();
我使用日期基类运行的测试看起来适用于项目和包含的子项的过滤。它确实需要显式地向过滤器调用提供类型。