Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework 5 performing full table scan

I have the following code:

public List<anEntity> Get(int page, int pagesize, Func<anEntity, IComparable> orderby)
{            
    using (var ctx = new MyContext())
    {                
        return ctx.anEntity.OrderBy(orderby).Skip(pagesize * page).Take(pagesize).ToList();                    
    }           
}

When I check my database profile (SqlServer 2012) I can see an horrible full table scan without any "TOP" clause.

The interesting part:

If I do something similar but specifying a concrete orderby:

return ctx.anEntity.OrderBy(x => x.aField).Skip(pagesize * page).Take(pagesize).ToList();

The profile shows a beautiful "TOP" clause.

I would like to avoid having lot's of methods, one for each "orderby" possibility. Any hint would be very appreciated.

like image 506
Jordi Avatar asked Oct 03 '12 14:10

Jordi


People also ask

What is flexible entity mapping in EF Core?

Flexible entity mapping Entity types are commonly mapped to tables or views such that EF Core will pull back the contents of the table or view when querying for that type. EF Core 5.0 adds additional mapping options, where an entity can be mapped to a SQL query (called a "defining query"), or to a table-valued function (TVF):

How can I capture performance data from EF?

Another approach for capturing performance data is to collect information automatically emitted by either EF or the database driver via the DiagnosticSource interface, and then analyze that data or display it on a dashboard.

What is filtered include in EF Core?

The filtered include feature, introduced in EF Core 5.0, also allows you to limit which related entities you'd like to load, while keeping the loading process eager and therefore doable in a single roundtrip: In other scenarios, we may not know which related entity we're going to need before we get its principal entity.

How does Entity Framework perform SQL queries?

Entity Framework is going to perform those operations one by one. If our SQL query would look something like: “UPDATE Posts SET ViewCount = ViewCount + 1 WHERE OwnerUserId = 9” to perform an UPDATE on all rows matching a predicate, then in Entity Framework, when we’ll write this in C#, we’ll have many more queries.


1 Answers

That's because your orderby parameter is a function rather than expression. There is no way to translate an arbitrary function into SQL, so all your data has to be on the client side before that function is called.

Change the parameter type to Expression<Func<anEntity, T>>, where T is a new generic parameter that you should add to your Get method, and it will work as expected.

Of course, you won't be able to use a custom IComparable, but there is no way around that: custom code cannot be translated into SQL.

like image 162
Fyodor Soikin Avatar answered Oct 20 '22 09:10

Fyodor Soikin