如何在 Entity Framework 中计算 时间差 ?
咨询区
ison
我的项目中有一个需求,需要使用 Entity Framework 实现 日期差
的计算逻辑,参考如下代码:
var now = DateTime.UtcNow;
db.Items.OrderBy(x => x.SomeInteger + (x.Date - now).Days);
但很奇怪,上面的代码会抛下面的错误:
The LINQ expression 'orderby' could not be translated and will be evaluated locally.
在 .NET Framework 中我可以通过 DbFunctions.DiffDays
来实现此需求, 但在 ASP.NET Core
中我该如何实现呢?
回答区
Stephen LAI:
在 github 上有一个 issue 就和你的问题相关,貌似在 2.1+
后就已经修复了这个问题,github:https://github.com/dotnet/efcore/issues/10468
解决方案如下:
public static class DbUtility
{
public static int DateDiff(string diffType, DateTime startDate, DateTime endDate)
{
throw new InvalidOperationException($"{nameof(DateDiff)} should be performed on database");
}
}
然后修改 ApplicationDbContext
类。
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.HasDbFunction(typeof(DbUtility)
.GetMethod(nameof(DbUtility.DateDiff)))
.HasTranslation(args => {
var newArgs = args.ToArray();
newArgs[0] = new SqlFragmentExpression((string)((ConstantExpression)newArgs[0]).Value);
return new SqlFunctionExpression(
"DATEDIFF",
typeof(int),
newArgs);
});
}
最后像下面这样使用。
DbUtility.DateDiff("day", x.DateAdded, now)
Stephen LAI:
在 ASP.NET Core
中你完全可以使用 SQL 提供的原生函数,由原来的 DbFunctions.DiffDays
改成 EF.Functions.DateDiffDay
即可, 参考如下代码:
var lstPeople = cxt
.People.Where(p => EF.Functions.DateDiffDay(p.Birth, DateTime.Now) > 0 )
.ToList();
点评区
其实用 EntityFramework 我还是那句话,如果你的项目业务复杂度不是很高的化,完全可以使用 EF 是一点问题都没有的,一旦复杂度上去了,用 EF 反而是一种负担,比如:100行的Linq
和 100行的sql
,哪一种会把你看晕呢?
评论