简体   繁体   English

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

[英]Entity Framework, Repository pattern and let statements

Trying to implement a correct Repository pattern with Entity Framework, I'm stumbling over some issues with let statements. 尝试使用Entity Framework实现正确的Repository模式,我对let语句的一些问题感到磕磕绊绊。 What I want to do is: 我想做的是:

var customer = (from cus in Customers.GetAll()
                let brokerExists = InsuredBrokers.GetAll().Any(ib => ib.INS_Id == cus.INS_Id)
            // ... more stuff

But this will give me an error 但这会给我一个错误

System.NotSupportedException: 'LINQ to Entities does not recognize the method 'System.Linq.IQueryable`1[ SNIP .DataModel.EA_INB_InsuredBrokers_TB] GetAll()' method, and this method cannot be translated into a store expression.' System.NotSupportedException: 'LINQ to Entities无法识别方法'System.Linq.IQueryable`1 [ SNIP .DataModel.EA_INB_InsuredBrokers_TB] GetAll()'方法,并且此方法无法转换为商店表达式。

What I instead can do is: 我可以做的是:

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

However, this breaks any point in using the Repository pattern. 但是,这打破了使用Repository模式的任何一点。 When I search for answers, people say to put it in a query on its own and reference it from memory, but since I actually have the customer's Id ( INS_Id ) in the let statement, I cannot do that. 当我搜索答案时,人们会说它自己把它放在查询中并从内存中引用它,但由于我实际上在let语句中有客户的Id( INS_Id ),所以我不能这样做。

GetAll() is like: GetAll()就像:

public IQueryable<T> GetAll()
{
    return _context.Set<T>().AsQueryable();
}

Are there any clever ways to get around this? 有没有聪明的方法来解决这个问题?

You have to move InsuredBrokers.GetAll() out of the query: 您必须将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

Then it will work fine. 然后它会正常工作。 Since GetAll returns IQueryable and you don't enumerate it - this has no negative effect and there will still be one query to database, just like in your example with _context . 由于GetAll返回IQueryable并且您没有枚举它 - 这没有负面影响,并且仍然会有一个查询到数据库,就像在您的示例中使用_context

The reason is let statement is compiled like this: 原因是let语句编译如下:

Customers.GetAll().Select(cus => new {cus, brokerExists = InsuredBrokers.GetAll().Any(ib => ib.INS_Id == cus.INS_Id)}

Which means your call to InsuredBrokers.GetAll() is part of expression tree (it's inside Select expression), and entity framework cannot (will not) just call it to obtain value. 这意味着你对InsuredBrokers.GetAll()调用是表达式树的一部分(它在Select表达式中),实体框架不能(不会)只是调用它来获取值。 It will try to translate it to SQL query, but has no idea what to do with GetAll method. 它会尝试将其转换为SQL查询,但不知道如何处理GetAll方法。

I assume you are trying to do a left join. 我假设您正在尝试左连接。

Your query: 您的查询:

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

If you need entries for no maches use DefaultIfEmpty . 如果您需要没有匹配的条目,请使用DefaultIfEmpty

You can refer to this for more on the same. 您可以参考这个更多关于一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM