Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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.'

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. 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.

GetAll() is like:

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

Are there any clever ways to get around this?

like image 534
SamiHuutoniemi Avatar asked Sep 03 '26 07:09

SamiHuutoniemi


1 Answers

You have to move InsuredBrokers.GetAll() out of the query:

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.

The reason is let statement is compiled like this:

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. It will try to translate it to SQL query, but has no idea what to do with GetAll method.

like image 143
Evk Avatar answered Sep 05 '26 22:09

Evk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!