[英]Entity Framework, Repository pattern and let statements
尝试使用Entity Framework实现正确的Repository模式,我对let语句的一些问题感到磕磕绊绊。 我想做的是:
var customer = (from cus in Customers.GetAll()
let brokerExists = InsuredBrokers.GetAll().Any(ib => ib.INS_Id == cus.INS_Id)
// ... more stuff
但这会给我一个错误
System.NotSupportedException: 'LINQ to Entities无法识别方法'System.Linq.IQueryable`1 [ SNIP .DataModel.EA_INB_InsuredBrokers_TB] GetAll()'方法,并且此方法无法转换为商店表达式。
我可以做的是:
var customer = (from cus in Customers.GetAll()
let brokerExists = _context.Set<EA_INB_InsuredBrokers_TB>().Any(ib => ib.INS_Id == cus.INS_Id)
// ... more stuff
但是,这打破了使用Repository模式的任何一点。 当我搜索答案时,人们会说它自己把它放在查询中并从内存中引用它,但由于我实际上在let语句中有客户的Id( INS_Id
),所以我不能这样做。
GetAll()
就像:
public IQueryable<T> GetAll()
{
return _context.Set<T>().AsQueryable();
}
有没有聪明的方法来解决这个问题?
您必须将InsuredBrokers.GetAll()
移出查询:
var allBrokers = InsuredBrokers.GetAll();
var customer = (from cus in Customers.GetAll()
let brokerExists = allBrokers.Any(ib => ib.INS_Id == cus.INS_Id)
// ... more stuff
然后它会正常工作。 由于GetAll
返回IQueryable
并且您没有枚举它 - 这没有负面影响,并且仍然会有一个查询到数据库,就像在您的示例中使用_context
。
原因是let
语句编译如下:
Customers.GetAll().Select(cus => new {cus, brokerExists = InsuredBrokers.GetAll().Any(ib => ib.INS_Id == cus.INS_Id)}
这意味着你对InsuredBrokers.GetAll()
调用是表达式树的一部分(它在Select
表达式中),实体框架不能(不会)只是调用它来获取值。 它会尝试将其转换为SQL查询,但不知道如何处理GetAll
方法。
我假设您正在尝试左连接。
您的查询:
var query = from customer in Customers
join broker in InsuredBrokers
on customer.InsertId equals broker.InsertId
into resutGroups
select new { Name = broker.Name, InsertId= broker.InsertId};
如果您需要没有匹配的条目,请使用DefaultIfEmpty 。
您可以参考这个更多关于一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.