Linq .NET 5 中的 DatePart 函数使用可变间隔

Posted

技术标签:

【中文标题】Linq .NET 5 中的 DatePart 函数使用可变间隔【英文标题】:DatePart function in Linq .NET 5 using variable interval 【发布时间】:2021-06-19 08:31:39 【问题描述】:

对于 EF Core 5,应使用 SqlFunctionExpression 构造来使用 DatePart 函数,如下所示:

public int? DatePart(string datePartArg, DateTime? 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(NotificationDbContext) // Your DB Context
                .GetRuntimeMethod(nameof(NotificationDbContext.DatePart), new[]  typeof(string), typeof(DateTime) );
            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
                        )
                    );
        

以后我们可以这样称呼它

_context.DatePart("day", x.Date);

但是我们如何传递变量而不是像下面这样的静态“天”

string daysInterval="day";
_context.DatePart(daysInterval, x.Date);

daysInterval 将由基于条件返回年、月或日的函数初始化。那么我们如何一般地传递​​ daysInterval 而不是硬编码呢?

【问题讨论】:

【参考方案1】:

我认为这是不可能的,因为 DATEPART 的第一个参数无法参数化。 EG SQL 看起来像:

select datepart(day,getdate())

不是

select datepart('day',getdate())

还有这个查询

_context.DatePart(daysInterval, x.Date);

将使用daysInterval 的参数进行翻译。 AFAIK 要做到这一点,您是否必须转换查询表达式并用文字表达式动态替换变量表达式,这是太多的工作。

或者提供您自己的 TSQL 标量函数,该函数将 varchar 作为第一个参数。喜欢

create function datepart2(@interval varchar(20), @d datetime2)
returns int
as
begin
  if @interval = 'day'
    return datepart(day,@d)
  else if @interval = 'second'
    return datepart(second,@d)
  --. . .

  return -1
end

并像这样注册它:

modelBuilder.HasDbFunction(datePartMethodInfo)
   .HasTranslation(args =>
            new SqlFunctionExpression("dbo.DATEPART2",
                new[]
                
                    args.ToArray()[0],
                    args.ToArray()[1]
                ,
                true,
                new[]  false, false ,
                typeof(int?),
                null
            )
        );

【讨论】:

以上是关于Linq .NET 5 中的 DatePart 函数使用可变间隔的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET中的Linq怎么用?

在 sql asp.net mvc 5 中使用 linq 时如何格式化记录中的数据?

.NET 2.0 运行时上的 LINQ

sql如何按日期中的月份查询

SQL 到 Linq - NET CORE 5

C#中的Linq to Xml详解