实体框架,存储库模式和let语句

时间:2018-03-02 07:55:24

标签: c# entity-framework linq

尝试使用Entity Framework实现正确的存储库模式,我在使用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();
}

有没有聪明的方法来解决这个问题?

2 个答案:

答案 0 :(得分:2)

您必须将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方法。

答案 1 :(得分:-1)

我假设您正在尝试进行左连接。

您的查询:

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};

如果您需要不使用商品的条目,请使用this

您可以参考{{3}}获取更多信息。