【问题标题】:LINQ to Entities does not recognize the method(Access to very large database)LINQ to Entities 无法识别该方法(访问非常大的数据库)
【发布时间】:2018-01-08 23:18:42
【问题描述】:

我有一个包含 200 万条记录的数据库,我必须对它们进行排序并以 JSON 格式输出结果(WebAPI 项目)。

这是我的代码:

CODE1

var start = Convert.ToDateTime(startdatetime.Split(new[] { ':' }, 2)[0]).Date;
        var end = Convert.ToDateTime(enddatetime.Split(new[] { ':' }, 2)[0]).Date;

        var result = (from request in db.Requests
                      where ((Convert.ToDateTime(request.DateTime.Split(new[] { ':' }, 2)[0]).Date >= start)
                     &&
                     (Convert.ToDateTime(request.DateTime.Split(new[] { ':' }, 2)[0]).Date <= end))
                      group request.IP_or_Host by request.IP_or_Host into g

                      orderby (g.Count()) descending

                      select g.Key).Distinct().Take(n).ToList();
        return result;

此代码抛出错误:

LINQ to Entities 无法识别该方法

之前是这样的:

CODE2

var start = Convert.ToDateTime(startdatetime.Split(new[] { ':' }, 2)[0]).Date;
            var end = Convert.ToDateTime(enddatetime.Split(new[] { ':' }, 2)[0]).Date;



            var result = (from request in db.Requests.ToList()
                          where ((Convert.ToDateTime(request.DateTime.Split(new[] { ':' }, 2)[0]).Date >= start)
                         &&
                         (Convert.ToDateTime(request.DateTime.Split(new[] { ':' }, 2)[0]).Date <= end))
                          group request.IP_or_Host by request.IP_or_Host into g

                          orderby (g.Count()) descending

                          select g.Key).Distinct().Take(n).ToList();
            return result;

但是如果数据库有太多的记录,它会抛出一个内存不足的异常。要使用 LINQ 以内存高效的方式从数据库中检索和排序数据,我需要做什么?

【问题讨论】:

  • 您正在将立即执行的函数与查询中的表达式混合在一起;这在 Entity Framework 6 中是不允许的(Core 对它的支持有限)。您应该将查询之外的一些参数预先计算为临时变量。诸如DateTime.SplitConvert.ToDateTime 之类的东西。有关更多信息,请参阅this 答案。
  • 所以db中的DateTime列不是DateTime类型而是nvarchar?
  • @DanielLorenz 是的,我将 DateTime 像字符串一样存储在我的数据库中,这种格式 "08/Mar/2004:07:07:13 -0800" ,因为那时我必须只按日期对记录进行排序,但我也必须存储时间。
  • @BradleyUffner 我知道 EF 不允许使用函数表达式,但我不知道在这种情况下我能做什么。
  • 如果还不算太晚,我只需创建两列。一个用于日期,一个用于时间。否则,也许看看 SqlFunctuons 类。

标签: c# asp.net .net entity-framework linq


【解决方案1】:

对于 DateTime,您可以使用 EntityFunctions 或 SqlFunctions,具体取决于版本。

How to Call Database Functions

EntityFunctions

您使用 ToList() 解决问题的方式,只是将所有内容加载到内存中。使用 ToList() 后,您将能够调用常规函数,但根据数据量的不同,它可能代价高昂且速度缓慢。

如果可以管理,最好在数据库中过滤。

另一种选择是向您的数据库添加第二列,其中包含实际的日期时间。您可以使用旧数据的 SQL 脚本来执行此操作,并从现在开始更改您的保存方法。

【讨论】:

    猜你喜欢
    • 2021-11-06
    相关资源
    最近更新 更多