EF Core中以下语句的等效项是什么?
SqlFunctions.DatePart("week", x.MyDate)
EF.Functions
似乎没有DatePart
方法。
答案 0 :(得分:2)
对于ef核心3.1来说,解决方案几乎没有什么不同,应该首先将参数转换为SqlConstantExpression
,然后将其Value
传递给SqlFragmentExpression
构造函数:
public static class DbFunctionExtensions
{
public static int? DatePart(string type, DateTime? date) => throw new Exception();
public static void ConfigureDbFunctions(this ModelBuilder modelBuilder)
{
var mi = typeof(DbFunctionExtensions).GetMethod(nameof(DatePart));
modelBuilder.HasDbFunction(mi, b => b.HasTranslation(e =>
{
var ea = e.ToArray();
var args = new[]
{
new SqlFragmentExpression((ea[0] as SqlConstantExpression).Value.ToString()),
ea[1]
};
return SqlFunctionExpression.Create(nameof(DatePart), args, typeof(int?), null);
}));
}
}
答案 1 :(得分:2)
对于 EF Core 5,它甚至不同,因为 SqlFunctionExpression.Create
工厂现已过时,应改用 SqlFunctionExpression
构造。这是更新后的代码(如果将其添加到数据库上下文中):
public partial class ApplicationDbContext : DbContext
{
public int? DatePart(string datePartArg, DateTimeOffset? date) => throw new InvalidOperationException($"{nameof(DatePart)} cannot be called client side.");
protected override void OnModelCreating(ModelBuilder builder)
{
var methodInfo = typeof(DbFunctionExtensions).GetMethod(nameof(DatePart));
var datePartMethodInfo = typeof(ApplicationDbContext) // Your DB Context
.GetRuntimeMethod(nameof(ApplicationDbContext.DatePart), new[] { typeof(string), typeof(DateTimeOffset) });
builder.HasDbFunction(datePartMethodInfo)
.HasTranslation(args =>
new SqlFunctionExpression("DATEPART",
new[]
{
new SqlFragmentExpression((args.ToArray()[0] as SqlConstantExpression).Value.ToString()),
args.ToArray()[1]
},
true,
new[] { false, false },
typeof(int?),
null
)
);
}
}
注意:您可以根据需要切换到 DateTime
而不是 DateTimeOffset
。
(该异常与 EF Core 5 无关,对于稍后处理代码或尝试调用方法客户端的任何人来说,这会更清楚)。
答案 2 :(得分:1)
可以通过将日期部分SQL函数与DbFunctionAttribute包装在一起来使用它。 棘手的部分是告诉ef核心不要将datepart类型参数作为字符串处理。示例:
DbContext:
public int? DatePart(string datePartArg, DateTime? date) => throw new Exception();
public void OnModelCreating(DbModelBuilder modelBuilder) {
var methodInfo = typeof(DbContext).GetRuntimeMethod(nameof(DatePart), new[] { typeof(string), typeof(DateTime) });
modelBuilder
.HasDbFunction(methodInfo)
.HasTranslation(args => new SqlFunctionExpression(nameof(DatePart), typeof(int?), new[]
{
new SqlFragmentExpression(args.ToArray()[0].ToString()),
args.ToArray()[1]
}));
}
查询:
repository.Where(x => dbContext.DatePart("week", x.CreatedAt) > 10);
更多信息:https://github.com/aspnet/EntityFrameworkCore/issues/10404
当心不要在DbContext的接口上调用DbFunction方法。调用必须直接在DbContext实例上进行。