[英]Entity Framework Share Queries
I don't quite know how to word this, so I'm just going to explain my scenario. 我不太清楚该如何措辞,因此我将解释我的情况。
I have a scenario where I have a TerminationDate
field on an EmploymentHistory
table that can be null, or a date in the future. 我有一个场景,在
EmploymentHistory
表上有一个TerminationDate
字段,该字段可以为null或将来的日期。 EmploymentHistory
joins to an Employees
table and it's a 1:M relationship, where a single Employee
can have multiple EmploymentHistory
records. EmploymentHistory
联接到一个Employees
表,它是一个1:M关系,其中一个Employee
可以拥有多个EmploymentHistory
记录。 That Employees
table joins to a lot of different places such as a Users
table that represents the front end portal the Employees
can log in to. 该
Employees
表联接到许多不同的地方,例如Users
表,该表代表Employees
可以登录的前端门户。
I frequently need to grab only the active employees. 我经常只需要抓住在职员工。 The SQL logic for being active is
WHERE TerminationDate IS NULL OR TerminationDate >= GETDATE()
. 处于活动状态的SQL逻辑是
WHERE TerminationDate IS NULL OR TerminationDate >= GETDATE()
。 So if TerminationDate is null or if it's set in the future. 因此,如果TerminationDate为null或在以后设置。
So in EF I have these queries like this: 因此,在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();
etc 等等
This logic shows up in about 5 different places. 该逻辑显示在大约5个不同的位置。 How do I share the
EmploymentHistory.Any(eh => eh.TerminationDate == null || eh.TerminationDate >= DateTime.Today
part of the logic when the base nav prop may be different? Tried playing with Expression<Func<T, bool>>
but got no where other than I think I have a solution if I can make all the Entities that need this inherit from a Base and could always assume there's a nav prop called Employee sitting there and the Base is my T
. If I try an extension method, EF Core can only evaluate it client side, not server side. 我如何共享
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只能在客户端进行评估,而不能在服务器端进行评估。
You could write an expression for the EmploymentHistory
: Expression<Func<EmploymentHistory, bool>> activeEmployee = eh => eh.TerminationDate == null || eh.TerminationDate >= DateTime.Today;
您可以为
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;
And use it like so: 并像这样使用它:
context.Employees.Where(e => e.EmploymentHistory.Any(activeEmployee)).ToList();
and 和
context.Users.Where(u => u.Employee.EmploymentHistory.Any(activeEmployee)).ToList();
. 。
It's not a huge reduction in code, but a lot less typing, and even better if you need to change the logic for some reason and don't want to change it everywhere is shows up. 这并不是代码的大幅减少,但是却减少了很多输入,甚至在由于某种原因需要更改逻辑并且不想在任何地方都更改逻辑的情况下甚至更好。
There are a number of ways to do this. 有很多方法可以做到这一点。 Using SQL Server and EF you could
使用SQL Server和EF,您可以
I tried option one in an older version of EF and it took forever to work through it. 我在较旧版本的EF中尝试了选项一,花了很长时间才能完成。 The performance wasn't great and I never tried it again.
表现不佳,我再也没有尝试过。 It looks like this has gotten easier in newer versions of EF though, so you're welcome to give it a try.
不过,在新版本的EF中,这似乎变得越来越容易,因此欢迎您尝试一下。
Option 2 probably offers the best balance of performance and accuracy since you can optimize the query for the view and then still greedy load the data for best efficiency. 选项2可能会在性能和准确性之间达到最佳平衡,因为您可以优化视图查询,然后仍然贪婪地加载数据以获得最佳效率。
Option 3 works a lot like option 2 and makes for the simplest C# code, but it's not going to be quite as efficient since it will have to handle the columns individually rather than in aggregate. 选项3与选项2的工作原理非常相似,并且使用最简单的C#代码,但是效率将不如以前那样高,因为它必须单独处理而不是汇总处理列。
There are times that I've found you have to use materialized information and it does offer the absolute best performance since there's no added calculation at runtime. 有时,我发现您必须使用具体化的信息,并且它确实提供了绝对最佳的性能,因为在运行时没有添加任何计算。 You risk your data being out of sync though, so I would reserve it for only the most severe cases where that performance is critical.
但是,您可能会面临数据不同步的风险,因此,我仅将其保留在性能至关重要的最严重情况下。
The bug that @Rounder referenced in his comment on @WeskerTyrant 's answer here has now been resolved in EF Core. 这@Rounder在他@WeskerTyrant的答复意见中引用的错误这里现在已经解决了在EF核心。
So, you can do something like this: 因此,您可以执行以下操作:
Expression<Func<T, bool>> IsActiveEmployee =
eh => eh.TerminationDate == null ||
eh.TerminationDate >= DateTime.Today
And then call it like: 然后像这样调用它:
context.Users.AsQueryable().Where(IsActiveEmployee).ToList();
Notice the addition of the .AsQueryable()
that allows the .Where()
to accept an Expression
. 注意添加了
.AsQueryable()
,它允许.Where()
接受一个Expression
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.