繁体   English   中英

实体框架共享查询

[英]Entity Framework Share Queries

我不太清楚该如何措辞,因此我将解释我的情况。

我有一个场景,在EmploymentHistory表上有一个TerminationDate字段,该字段可以为null或将来的日期。 EmploymentHistory联接到一个Employees表,它是一个1:M关系,其中一个Employee可以拥有多个EmploymentHistory记录。 Employees表联接到许多不同的地方,例如Users表,该表代表Employees可以登录的前端门户。

我经常只需要抓住在职员工。 处于活动状态的SQL逻辑是WHERE TerminationDate IS NULL OR TerminationDate >= GETDATE() 因此,如果TerminationDate为null或在以后设置。

因此,在EF中,我有以下查询:

// Grab all Active Employees context.Employees.Where(e => e.EmploymentHistory.Any(eh => eh.TerminationDate == null || eh.TerminationDate >= DateTime.Today).ToList();

// Get all Users context.Users.Where(u => u.Employee.EmploymentHistory.Any(eh => eh.TerminationDate == null || eh.TerminationDate >= DateTime.Today).ToList();

等等

该逻辑显示在大约5个不同的位置。 我如何共享EmploymentHistory.Any(eh => eh.TerminationDate == null || eh.TerminationDate >= DateTime.Today ,当基础导航道具可能不同时, EmploymentHistory.Any(eh => eh.TerminationDate == null || eh.TerminationDate >= DateTime.Today的逻辑部分尝试过与Expression<Func<T, bool>>但我认为我有解决方案,如果我可以使所有需要此实体的实体都从Base继承,并且可以始终假设有一个名为Employee的导航道具坐在那里,而Base是我的T尝试一种扩展方法,EF Core只能在客户端进行评估,而不能在服务器端进行评估。

您可以为EmploymentHistory编写一个表达式: Expression<Func<EmploymentHistory, bool>> activeEmployee = eh => eh.TerminationDate == null || eh.TerminationDate >= DateTime.Today; Expression<Func<EmploymentHistory, bool>> activeEmployee = eh => eh.TerminationDate == null || eh.TerminationDate >= DateTime.Today;

并像这样使用它:
context.Employees.Where(e => e.EmploymentHistory.Any(activeEmployee)).ToList();

context.Users.Where(u => u.Employee.EmploymentHistory.Any(activeEmployee)).ToList();

这并不是代码的大幅减少,但是却减少了很多输入,甚至在由于某种原因需要更改逻辑并且不想在任何地方都更改逻辑的情况下甚至更好。

有很多方法可以做到这一点。 使用SQL Server和EF,您可以

  1. 在SQL中创建一个函数并将其导入EF。 这有点棘手,但是可以做到。
  2. 在执行计算的服务器上创建一个视图,并在EF中定义关系,以便您可以从视图中调用并贪婪地从那里加载所需的信息。
  3. 在表中添加一个计算列,以显示用户是否处于活动状态。
  4. 在表中添加一个实例化列,以跟踪用户是否处于活动状态,并维护该列以及现有数据。

我在较旧版本的EF中尝试了选项一,花了很长时间才能完成。 表现不佳,我再也没有尝试过。 不过,在新版本的EF中,这似乎变得越来越容易,因此欢迎您尝试一下。

选项2可能会在性能和准确性之间达到最佳平衡,因为您可以优化视图查询,然后仍然贪婪地加载数据以获得最佳效率。

选项3与选项2的工作原理非常相似,并且使用最简单的C#代码,但是效率将不如以前那样高,因为它必须单独处理而不是汇总处理列。

有时,我发现您必须使用具体化的信息,并且它确实提供了绝对最佳的性能,因为在运行时没有添加任何计算。 但是,您可能会面临数据不同步的风险,因此,我仅将其保留在性能至关重要的最严重情况下。

这@Rounder在他@WeskerTyrant的答复意见中引用的错误这里现在已经解决了在EF核心。

因此,您可以执行以下操作:

Expression<Func<T, bool>> IsActiveEmployee =
    eh => eh.TerminationDate == null ||
          eh.TerminationDate >= DateTime.Today

然后像这样调用它:

context.Users.AsQueryable().Where(IsActiveEmployee).ToList();

注意添加了.AsQueryable() ,它允许.Where()接受一个Expression

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM