与 EF Core 中的 SqlFunctions.DatePart 等效

And*_*ijo 5 entity-framework-core .net-core

EF Core 中以下语句的等效项是什么?

SqlFunctions.DatePart("week", x.MyDate)
Run Code Online (Sandbox Code Playgroud)

EF.Functions好像没有DatePart方法。

Zia*_*iki 10

对于 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
                    )
                );
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:您可以根据需要切换到DateTime而不是。DateTimeOffset

(该异常与 EF Core 5 无关,只是对于稍后处理代码或尝试调用客户端方法的任何人来说更加清楚)。


cyp*_*tus 6

可以通过用 DbFunctionAttribute 包装它来使用 datepart SQL 函数。棘手的部分是告诉 ef core 不要将 datepart 类型参数作为字符串处理。例子:

数据库上下文ef core <= 2.1

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]
                }));
}
Run Code Online (Sandbox Code Playgroud)

DbContext ef core >= 3.1(静态SqlFunctionExpression.Create调用而不是 ctor):

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 => SqlFunctionExpression.Create(nameof(DatePart), new[]
                {
                        new SqlFragmentExpression(args.ToArray()[0].ToString()),
                        args.ToArray()[1]
                }, typeof(int?), null));
}
Run Code Online (Sandbox Code Playgroud)

询问:

repository.Where(x => dbContext.DatePart("week", x.CreatedAt) > 10);
Run Code Online (Sandbox Code Playgroud)

更多信息:https : //github.com/aspnet/EntityFrameworkCore/issues/10404

注意不要在 DbContext 的接口上调用 DbFunction 方法。调用必须直接发生在 DbContext 实例上。

编辑:因为ef core 3.1您可以使用静态方法SqlFunctionExpression.Create而不是 ctor: