LINQ querying using an entity object not in the database - Error: LINQ to Entities does not recognize the method

LINQ querying using an entity object not in the database - Error: LINQ to Entities does not recognize the method

我有一个从数据库创建的 Entity Framework v5 模型。 table Season 有一个对应的实体叫做 Season。 我需要计算 Project_Group 每年的季节的最短开始日期和最长结束日期。然后,我需要能够在其他 LINQ 查询中加入那些每年的 min/max 季节值。为此,我在我的数据访问层项目中创建了一个 SeasonLimits class。 (A SeasonLimits table 存在于数据库中。)

public partial class SeasonLimits : EntityObject
{
    public int Year { get; set; }
    public DateTime Min_Start_Date { get; set; }
    public int Min_Start_Date_ID { get; set; }
    public DateTime Max_End_Date { get; set; }
    public int Max_End_Date_ID { get; set; }

    public static IQueryable<SeasonLimits> QuerySeasonLimits(MyEntities context, int project_Group_ID)
    {
        return context
            .Season
            .Where(s => s.Locations.Project.Project_Group.Any(pg => pg.Project_Group_ID == project_Group_ID))
            .GroupBy(x => x.Year)
            .Select(sl => new SeasonLimits
            {
                Year = sl.Key,
                Min_Start_Date = sl.Min(d => d.Start_Date),
                Min_Start_Date_ID = sl.Min(d => d.Start_Date_ID),
                Max_End_Date = sl.Max(d => d.End_Date),
                Max_End_Date_ID = sl.Max(d => d.End_Date_ID)
            });
    }
}

// MVC Project
var seasonHoursByYear =
    from d in context.AuxiliaryDateHours
    from sl in SeasonLimits.QuerySeasonLimits(context, pg.Project_Group_ID)
    where d.Date_ID >= sl.Min_Start_Date_ID
        && d.Date_ID < sl.Max_End_Date_ID
    group d by new
    {
        d.Year
    } into grp4
    orderby grp4.Key.Year
    select new
    {
        Year = grp4.Key.Year,
        HoursInYear = grp4.Count()
    };

在我的 MVC 项目中,每当我尝试在 LINQ 查询 JOIN 中使用 QuerySeasonLimits 方法时,我都会收到消息,

"LINQ to Entities does not recognize the method 'System.Linq.IQueryable`1[MyDAL.SeasonLimits] QuerySeasonLimits(MyDAL.MyEntities, MyDAL.Project_Group)' method, and this method cannot be translated into a store expression."

生成此错误是因为 SeasonLimits 不是数据库中存在的实体吗?如果不能以这种方式完成,是否有另一种方法来引用逻辑,以便它可以在其他 LINQ 查询中使用?

EF 正在尝试将您的查询转换为 SQL,并且由于您的方法与生成的 SQL 之间没有直接映射,因此您遇到了错误。

第一个选项是不使用该方法,而是直接在原始查询中写入该方法的内容(我现在不确定这是否可行,因为我没有 VS 运行).在这种情况下,你很可能会得到一个非常复杂的 SQL,性能很差。

所以这里出现了第二个选项:不要害怕使用多个查询来获得你需要的东西。有时向数据库发送更简单的查询并继续在 C# 代码中进行修改(聚合、选择等)也很有意义。每当您尝试枚举查询时,或者如果您使用 ToListToDictionaryToArrayToLookup 方法之一,或者如果您正在使用 FirstFirstOrDefaultSingleSingleOrDefault 调用(具体请参阅 LINQ documentation)。

一个可以修复您的查询的可能示例(但很可能不是最佳解决方案)是使用以下内容开始您的查询:

var seasonHoursByYear =
    from d in context.AuxiliaryDateHours.ToList()
    [...]

然后继续剩下的。这个微小的变化具有根本性的影响:

  1. 通过调用ToList 数据库将立即被查询并且整个 AuxiliaryDateHours table 将加载到应用程序中(如果 table 的行太多,这将是一个性能问题)
  2. 调用您的 QuerySeasonLimits 方法时将生成第二个查询(您 could/should 还包含一个 ToList 调用)
  3. seasonHoursByYear 查询的其余部分:where、分组...将在内存中进行

此时还有其他几点可能无关。

我还没有真正调查过你的代码的意图——因为这可能会导致进一步的优化——甚至是彻底的返工最终会给你带来更多的收益……

我去掉了SeasonLimits对象和QuerySeasonLimits方法,把方法的内容直接写在原来的查询中

// MVC Project
var seasonLimits =
    from s in context.Season
        .Where(s => s.Locations.Project.Project_Group.Any(pg => pg.Project_Group_ID == Project_Group_ID))
    group s by new
    {
        s.Year
    } into grp
    select new
    {
        grp.Key.Year,
        Min_Start_Date = grp.Min(x => x.Start_Date),
        Min_Start_Date_ID = grp.Min(x => x.Start_Date_ID),
        Max_End_Date = grp.Max(x => x.End_Date),
        Max_End_Date_ID = grp.Max(x => x.End_Date_ID)
    };

var seasonHoursByYear =
    from d in context.AuxiliaryDateHours
    from sl in seasonLimits
    where d.Date_ID >= sl.Min_Start_Date_ID
        && d.Date_ID < sl.Max_End_Date_ID
    group d by new
    {
        d.Year
    } into grp4
    orderby grp4.Key.Year
    select new
    {
        Year = grp4.Key.Year,
        HoursInYear = grp4.Count()
    };