我刚刚从Linq 2 SQL切换到Entity Framework,我在EF中看到了一些奇怪的行为,我希望有人可以提供帮助。我试过谷歌搜索,但我无法找到同样问题的其他人。我嘲笑了一个场景来解释这种情况。
如果我直接使用EF上下文,我可以在select中进行选择。例如,这执行得非常好:
// this is an Entity Framework context that inherits from ObjectContext
var dc = new MyContext();
var companies1 = (from c in dc.Companies
select new {
Company = c,
UserCount = (from u in dc.CompanyUsers
where u.CompanyId == c.Id
select u).Count()
}).ToList();
但是,如果我使用存储库返回IQueryable(甚至是ObjectSet或ObjectQuery)的存储库模式,我会得到一个NotSupportedException(LINQ to Entities无法识别方法'System.Linq.IQueryable`1)...
以下是我的存储库的示例:
public class Repository {
private MyContext _dc;
public Repository() {
_dc = new MyContext();
}
public IQueryable<Company> GetCompanies() {
return _dc.Companies;
}
public IQueryable<CompanyUser> GetCompanyUsers() {
return _dc.CompanyUsers;
}
}
//我正在另一个类中使用存储库(例如在我的服务层中)
var repository = new Repository();
var companies2 = (from c in repository.GetCompanies()
select new {
Company = c,
UserCount = (from u in repository.GetCompanyUsers()
where u.CompanyId == c.Id
select u).Count()
}).ToList();
上面的代码抛出NotSupportedException。
我意识到如果公司和公司用户之间存在关联,那么我可以简单地做到这一点并且它会正常工作:
var companies3 = (from c in repository.GetCompanies()
select new {
Company = c,
UserCount = (from u in c.CompanyUsers
select u).Count()
}).ToList();
...但我的例子只是一个更复杂的场景的简化版本,我没有实体之间的关联。
所以我很困惑为什么Entity Framework会抛出NotSupportedException。当我直接使用EF上下文时,查询是如何工作完全正常的,但如果我正在使用从另一个方法返回的IQueryable,则不支持它。这与Linq 2 SQL完美配合,但它似乎在Entity Framework中不起作用。
非常感谢任何见解。
提前致谢。
答案 0 :(得分:7)
我怀疑发生的事情是,EF在第一个repository.GetCompanyUsers()
的lambda中看到select
的表达式,并且不知道如何处理它,因为repository
不是EF上下文。我认为,如果直接传递IQueryable而不是返回它的表达式,它应该可以工作。
如果你这样做怎么样:
var companyUsers = repository.GetCompanyUsers();
var companies2 = (from c in repository.GetCompanies()
select new {
Company = c,
UserCount = (from u in companyUsers
where u.CompanyId == c.Id
select u).Count()
}).ToList();
答案 1 :(得分:3)
这是Linq to SQL / EF的一个奇怪的怪癖。显然,他们实现了一种从getter 属性转换为SQL的方法,但不是从getter 函数转换为SQL的方法。
如果您使用GetCompanyUsers()
这样的属性代替函数CompanyUsers
,它应该有用。
很奇怪呃?
所以而不是
public IQueryable<CompanyUser> GetCompanyUsers() {
return _dc.CompanyUsers;
}
你可以做
public IQueryable<CompanyUser> CompanyUsers {
get { return _dc.CompanyUsers; }
}
就参数化查询而言(显然,您无法对属性进行查询),请参阅我的问题:Custom function in Entity Framework query sometimes translates properly, sometimes doesn't
您也可以在酒店中拥有wheres
和selects
;他们会翻译得很好。例如,如果我的博客上有一篇文章表,其中包含一些不在线的文章:
public IQueryable<Article> LiveArticles {
get { return _dc.Articles.Where(a => !a.IsDraft); }
}
这也会减少您需要的参数化查询的数量。