C# LINQ to实体无法识别方法“System.LINQ.IQueryable”
当我尝试在子选择中调用我的存储库时,出现了此错误C# LINQ to实体无法识别方法“System.LINQ.IQueryable”,c#,entity-framework,C#,Entity Framework,当我尝试在子选择中调用我的存储库时,出现了此错误 IGrpTextRepository rep = new GrpTextRepository(); var query = new DetailViewModel { ViewDet = (from gh in _db.Grp select new MultiDetailViewModel {
IGrpTextRepository rep = new GrpTextRepository();
var query = new DetailViewModel
{
ViewDet = (from gh in _db.Grp
select new MultiDetailViewModel
{
Header = gh,
Txts = rep.FindAllLangTxtById(gh.GrpID)
}).ToList(),
Lang = _db.Language.ToList(),
};
我的界面是
public interface IGrpTextRepository
{
IQueryable<GrpText> FindAllLangTxtById(int GrpID);
}
public class GrpTextRepository : IGrpTextRepository
{
DBEntities db = new DBEntities();
public IQueryable<GrpText> FindAllLangTxtById(int GrpID)
{
return (from lang in db.Language
join gtxts in db.GrpText on lang.LangID equals gtxts.LangID into jointxt
from fintxt in jointxt.DefaultIfEmpty()
where fintxt.GrpID == GrpID
select fintxt);
}
}
下面是完整的错误消息
System.NotSupportedException:LINQ to Entities无法识别方法'System.LINQ.IQueryable'1[aaa.Models.GrpText]FindAllangtXtbyind32'方法,并且此方法无法转换为存储表达式。简单的解决方案是在选择之前添加一个.ToList
ViewDet = _db.Grp.ToList().Select(gh => new MultiDetailViewModel ...)
这样,初始请求将进入数据库,返回结果,然后您可以使用select语句对Linq to对象重新投影它们
但我必须问,为什么在组和文本之间没有FK关系,因此在这两者之间没有实体关联,允许您只访问gh.GrpText,并使用.Include访问延迟加载或急切加载的文本集合
正如@Doguhan Uluca在评论中指出的,使用ToList是有风险的,因为它会导致该表中的所有内容都被提取到内存中。您应该只在非常小的集合上使用它。正确的方法是修复数据库设计,以便高效查询。希望我能简明扼要地解释一下。。。您对IQueryable接口、延迟执行和表达式树了解多少?我已经在组和文本之间有了FK。我想创建一个与语言表左连接的子查询。我需要不同语言的每个组文本列表。如果组文本不是特定语言的traduct,我希望结果为null。我建议不要调用数据库表上的.ToList,除非你想在内存中加载整个表。@DoguhanUluca-那么,在这种情况下,调用.ToList的替代方法是什么呢?在这种情况下,正确的替代方法就是我建议的方法-使用FK关系,这样文本就可以惰性地或急切地加载。有时,如果你知道这是一张小桌子,托利斯是可以接受的,但通常,正如@DoguhanUluca指出的那样,这样做是错误的。您还可以投影到匿名类型,因为这可以转换为仅返回数据库中某些列的SELECT,但您仍需要在某个时候将其转换为非匿名类型,以便从方法中返回。@oonyalo最近我一直在创建视图,稍后将其与LINQ一起使用,以避免过度使用复杂的LINQ语句确实不能很好地工作。任何需要.ToList的操作,比如Distinct,在以后的代码中也需要动态LINQ操作,那么我建议使用数据库视图。