EF Core中的SqlFunctions.DatePart等效项

时间:2018-09-27 04:27:50

标签: .net-core entity-framework-core

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

SqlFunctions.DatePart("week", x.MyDate)

EF.Functions似乎没有DatePart方法。

3 个答案:

答案 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实例上进行。

相关问题