【问题标题】:DbFunctions.TruncateTime LINQ equivalent in EF COREEF CORE 中的 DbFunctions.TruncateTime LINQ 等效项
【发布时间】:2016-11-23 07:53:01
【问题描述】:

我的 .net 应用程序中有以下功能 LINQ

    public ActionResult Index()
    {
        Dictionary<DateTime?, List<Event>> result;
        result = (from events in db.Events.Include("Activity")
                      where events.IsActive
                      group events by DbFunctions.TruncateTime(events.DateTimeFrom) into dateGroup
                      select new { EventDate = dateGroup.Key, Events = dateGroup.ToList() }).ToDictionary(x => x.EventDate, x => x.Events);

        return View(result);
    }

当我在 EF Core 中使用它时,我无法使用 DbFunctions。如何重写它以使其在 Microsoft.EntityFrameworkCore 中工作?如果这有所作为,我正在使用 SQLite。

【问题讨论】:

  • 在 .Net Core 3+ 中可以使用 EF.Functions。

标签: sqlite linq entity-framework-core


【解决方案1】:

在 EF6 中使用 DbFunctions.TruncateTime 代替 DateTime.Date 属性,因为由于某种原因不支持后者。

在 EF Core 中不需要前者,因为 DateTime.Date 现在已被正确识别和翻译。

group events by events.DateTimeFrom.Date into dateGroup

不幸的是,目前还没有关于支持什么的文档,因此作为一般经验法则,请始终尝试相应的 CLR 方法/属性(如果有)并检查它是否转换为 SQL 以及如何转换。

【讨论】:

    【解决方案2】:

    要在 ASP.NET CORE 中使用 DbFunctions,您必须创建一个对象。

    var DbF = Microsoft.EntityFrameworkCore.EF.Functions;
    

    现在您可以轻松使用它了。

    var now = DateTime.Now;
    
    int count = db.Tbl.Count(w => DbF.DateDiffDay(now, w.RegisterDate) <= 3);
    

    更多详情github

    【讨论】:

    • 如何将对象分配给变量会导致其具有不同的方法/更改其在 C# 中的可访问性?
    • @Reinis 在运行时这个对象被QueryCompiler翻译成sql代码
    • 但是为什么需要分配呢?将EF.Functions 对象分配给变量如何改变TruncateTime 方法是否可访问?为什么不直接使用对象而不将其分配给变量?
    • @Reinis 那是因为我的代码澄清了。也可以直接使用EF.Functions.DateDiffDay()
    【解决方案3】:

    EF Core 尚不支持 DbFunction。但是,您可以使用“原始 Sql 查询”。

    你可以找到"Raw Sql Queries" here的文档

    您还可以跟踪 here 以获取 EF Core 的 DbFunctions

    【讨论】:

    • +100 用于提供跟踪链接!,现在我看到 .NET Core 2.0 有 EF.Functions。
    【解决方案4】:

    EF Core 3.0

    我终于找到了一个可行的答案。问题是我想在数据库中的 DateTime 列上按日期分组。

    对我来说关键是使用 EF.Property 函数。这允许该类具有用于添加该级别数据的 DateTime 属性,但下面允许我将其重新定义为日期。但是.. 我怀疑如果我在类上声明了属性,它已经允许我使用它不允许我做的 .Date 函数。

    因此,解决方案可能是在模型上定义属性,或者使用以下内容在您的查询中定义它。

    EF.Property(s, "dt").Date

    完整代码

    var myData = _context.ActivityItems
                                .GroupBy(a => new { nlid = a.lid, nsd = EF.Property<DateTime>(a, "dt").Date })
                                .Select(g => new
                                {
                                    g.Key.nlid,
                                    g.Key.nsd,
                                    cnt = g.Count()
                                });
    

    【讨论】:

    • 太棒了。在我的情况下,这有助于使用 npgsql 在 DateTimeOffset 属性上应用 DATE_TRUNC。
    【解决方案5】:

    我也设法在 Lambda 中重写了它并使其异步。似乎工作相同。

    var temp = await _context.Events.Where(x => x.IsActive)
                .Include(a => a.Activity)
                .GroupBy(x => x.DateTimeFrom.Date)
                .Select(g => new { EventDate = g.Key, Events = g.ToList() }).ToDictionaryAsync(x => x.EventDate, x => x.Events);
    

    【讨论】:

    • 所以您使用了.Date 对象的.Date 属性,并且它在EF Core 中工作?
    【解决方案6】:

    EF Core 2.0 现在支持将数据库函数映射到上下文中的静态方法。

    在此处查看“数据库标量函数映射”部分 - https://docs.microsoft.com/en-us/ef/core/what-is-new/

    【讨论】:

      【解决方案7】:

      就我而言,它以这种方式工作,而不是 DbFunctions.TruncateTime 或 EntityFunctions.TruncateTime-

      result = _context.ActivityItems.Where(a =>  a.DateTimeFrom.Value.Date == paramFilter.DateTimeFrom.Value.Date);
      

      它首先在服务器端将日期转换为where条件,然后与参数日期值进行比较-

      WHERE CONVERT(date, [a].[DateTimeFrom]) = @__paramFilter_DateTimeFrom_Value_Date_0
      

      【讨论】:

        猜你喜欢
        • 2021-04-27
        • 2019-03-02
        • 1970-01-01
        • 1970-01-01
        • 2020-06-12
        • 1970-01-01
        • 2020-04-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多