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# 代码中进行修改(聚合、选择等)也很有意义。每当您尝试枚举查询时,或者如果您使用 ToList
、ToDictionary
、ToArray
、ToLookup
方法之一,或者如果您正在使用 First
、FirstOrDefault
、Single
或 SingleOrDefault
调用(具体请参阅 LINQ documentation)。
一个可以修复您的查询的可能示例(但很可能不是最佳解决方案)是使用以下内容开始您的查询:
var seasonHoursByYear =
from d in context.AuxiliaryDateHours.ToList()
[...]
然后继续剩下的。这个微小的变化具有根本性的影响:
- 通过调用
ToList
数据库将立即被查询并且整个
AuxiliaryDateHours
table 将加载到应用程序中(如果 table 的行太多,这将是一个性能问题)
- 调用您的 QuerySeasonLimits 方法时将生成第二个查询(您 could/should 还包含一个
ToList
调用)
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()
};
我有一个从数据库创建的 Entity Framework v5 模型。 table Season 有一个对应的实体叫做 Season。
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# 代码中进行修改(聚合、选择等)也很有意义。每当您尝试枚举查询时,或者如果您使用 ToList
、ToDictionary
、ToArray
、ToLookup
方法之一,或者如果您正在使用 First
、FirstOrDefault
、Single
或 SingleOrDefault
调用(具体请参阅 LINQ documentation)。
一个可以修复您的查询的可能示例(但很可能不是最佳解决方案)是使用以下内容开始您的查询:
var seasonHoursByYear =
from d in context.AuxiliaryDateHours.ToList()
[...]
然后继续剩下的。这个微小的变化具有根本性的影响:
- 通过调用
ToList
数据库将立即被查询并且整个AuxiliaryDateHours
table 将加载到应用程序中(如果 table 的行太多,这将是一个性能问题) - 调用您的 QuerySeasonLimits 方法时将生成第二个查询(您 could/should 还包含一个
ToList
调用) 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()
};