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.
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):
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With