Skip to content

Commit 7fae285

Browse files
committed
Update Query documentation
Resolves#615 Resolves#1636 Resolves#1648 Resolves#1699 Resolves#1777
1 parent bb82f4a commit 7fae285

File tree

14 files changed

+339
-126
lines changed

14 files changed

+339
-126
lines changed
+4-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
---
22
title: Asynchronous Queries - EF Core
3-
author: rowanmiller
4-
ms.date: 01/24/2017
3+
author: smitpatel
4+
ms.date: 10/01/2019
55
ms.assetid: b6429b14-cba0-4af4-878f-b829777c89cb
66
uid: core/querying/async
77
---
88

99
# Asynchronous Queries
1010

11-
Asynchronous queries avoid blocking a thread while the query is executed in the database. This can be useful to avoid freezing the UI of a thick-client application. Asynchronous operations can also increase throughput in a web application, where the thread can be freed up to service other requests while the database operation completes. For more information, see [Asynchronous Programming in C#](https://docs.microsoft.com/dotnet/csharp/async).
11+
Asynchronous queries avoid blocking a thread while the query is executed in the database. This can be useful to avoid freezing the UI of a thick-client application. Asynchronous operations can also increase throughput in a web application, where the thread can be freed up to service other requests while the database operation completes. For more information, see [Asynchronous Programming in C#](/dotnet/csharp/async).
1212

1313
> [!WARNING]
1414
> EF Core does not support multiple parallel operations being run on the same context instance. You should always wait for an operation to complete before beginning the next operation. This is typically done by using the `await` keyword on each asynchronous operation.
@@ -18,4 +18,4 @@ Entity Framework Core provides a set of asynchronous extension methods that can
1818
> [!IMPORTANT]
1919
> The EF Core async extension methods are defined in the `Microsoft.EntityFrameworkCore` namespace. This namespace must be imported for the methods to be available.
2020
21-
[!code-csharp[Main](../../../samples/core/Querying/Async/Sample.cs#Sample)]
21+
[!code-csharp[Main](../../../samples/core/Querying/Async/Sample.cs#ToListAsync)]

entity-framework/core/querying/basic.md

-50
This file was deleted.

entity-framework/core/querying/client-eval.md

+37-44
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,62 @@
11
---
22
title: Client vs. Server Evaluation - EF Core
3-
author: rowanmiller
4-
ms.date: 10/27/2016
3+
author: smitpatel
4+
ms.date: 10/01/2019
55
ms.assetid: 8b6697cc-7067-4dc2-8007-85d80503d123
66
uid: core/querying/client-eval
77
---
88
# Client vs. Server Evaluation
99

10-
Entity Framework Core supports parts of the query being evaluated on the client and parts of it being pushed to the database. It is up to the database provider to determine which parts of the query will be evaluated in the database.
10+
In order to evaluate query on server as much as possible, Entity Framework Core converts parts of the query which can be evaluated on client side to convert them to parameters and rest of the query with generated parameters is given to database providers to determine what should be equivalent database query to do evaluation on the server. EF Core supports partial client evaluation in top level projection (essentially, the last call to `Select()`). If parts of query in top level projection cannot be translated to server, EF Core will fetch required data from server and evaluate it on client. If EF Core detects expression which cannot be translated to server in any other place then it throws runtime exception. See [how query works](xref:core/querying/how-query-works) to understand how EF Core determines what cannot be translated to server.
1111

12-
> [!TIP]
13-
> You can view this article's [sample](https://github.com/aspnet/EntityFramework.Docs/tree/master/samples/core/Querying) on GitHub.
12+
> [!NOTE]
13+
> Prior to version 3.0, Entity Framework Core supported parts of query to be evaluated on client anywhere in the query. See the [previous versions section](#previous-versions) for more details.
1414
1515
## Client evaluation
1616

17-
In the following example a helper method is used to standardize URLs for blogs that are returned from a SQL Server database. Because the SQL Server provider has no insight into how this method is implemented, it is not possible to translate it into SQL. All other aspects of the query are evaluated in the database, but passing the returned `URL` through this method is performed on the client.
18-
19-
<!-- [!code-csharp[Main](samples/core/Querying/ClientEval/Sample.cs?highlight=6)] -->
20-
``` csharp
21-
var blogs = context.Blogs
22-
.OrderByDescending(blog => blog.Rating)
23-
.Select(blog => new
24-
{
25-
Id = blog.BlogId,
26-
Url = StandardizeUrl(blog.Url)
27-
})
28-
.ToList();
29-
```
17+
> [!TIP]
18+
> You can view this article's [sample](https://github.com/aspnet/EntityFramework.Docs/tree/master/samples/core/Querying) on GitHub.
3019
31-
<!-- [!code-csharp[Main](samples/core/Querying/ClientEval/Sample.cs)] -->
32-
``` csharp
33-
public static string StandardizeUrl(string url)
34-
{
35-
url = url.ToLower();
20+
In the following example a helper method is used to standardize URLs for blogs which are returned from a SQL Server database. Because the SQL Server provider has no insight into how this method is implemented, it is not possible to translate it into SQL. All other aspects of the query are evaluated in the database, but passing the returned `URL` through this method is performed on the client.
3621

37-
if (!url.StartsWith("http://"))
38-
{
39-
url = string.Concat("http://", url);
40-
}
22+
[!code-csharp[Main](../../../samples/core/Querying/ClientEval/Sample.cs#ClientProjection)]
4123

42-
return url;
43-
}
44-
```
24+
[!code-csharp[Main](../../../samples/core/Querying/ClientEval/Sample.cs#ClientMethod)]
4525

46-
## Client evaluation performance issues
26+
## Unsupported client evaluation
4727

48-
While client evaluation can be very useful, in some instances it can result in poor performance. Consider the following query, where the helper method is now used in a filter. Because this can't be performed in the database, all the data is pulled into memory and then the filter is applied on the client. Depending on the amount of data, and how much of that data is filtered out, this could result in poor performance.
28+
While client evaluation can be very useful, in some instances it can result in poor performance. Consider the following query, in which the helper method is now used in a where filter. Because this can't be performed in the database, all the data needs to be pulled into memory and then the filter needs to be applied on the client. Depending on the amount of data on the server, and how much of that data is filtered out, this could result in poor performance. Hence Entity Framework Core blocks such client evaluation and throws a runtime exception.
4929

50-
<!-- [!code-csharp[Main](samples/core/Querying/ClientEval/Sample.cs)] -->
51-
``` csharp
52-
var blogs = context.Blogs
53-
.Where(blog => StandardizeUrl(blog.Url).Contains("dotnet"))
54-
.ToList();
55-
```
30+
[!code-csharp[Main](../../../samples/core/Querying/ClientEval/Sample.cs#ClientWhere)]
31+
32+
## Explicit client evaluation
33+
34+
In certain instances user may need to force into client evaluation explicitly like following cases
35+
36+
- Data is small so that doing evaluation on client does not cause huge performance penalty.
37+
- LINQ operator being used has no server side translation.
38+
39+
In such cases, user can explicitly opt into client evaluation by calling methods like `AsEnumerable` (or `AsAsyncEnumerable` for async).
40+
41+
[!code-csharp[Main](../../../samples/core/Querying/ClientEval/Sample.cs#ExplicitClientEval)]
42+
43+
## Potential memory leak in client evaluation
44+
45+
Since query translation and compilation is expensive, by default, EF Core caches compiled query plan. With client evaluation allowed in the top projection, the cached delegate can use client code. In most cases, EF Core generates parameters for client parts of the tree so that their values can be replaced when reusing the query plan. But with certain constants in expression tree, it cannot be converted to parameters. If the client code contains such constants then those objects cannot be garbage collected. If such object contains DbContext or other services inside it then it could cause memory usage of the app to grow over time. In order to avoid potential memory leak, EF Core throws exception whenever it encounter constants of type which cannot be mapped in current database providers. Common causes and their solutions are as follows:
46+
47+
- **Using instance method**: When using instance methods in client projection, the expression tree contains constant of the instance. If your method does not use any data from instance, consider making the method static. If you need instance data in the method body, then pass specific data as an argument to the method.
48+
- **Passing constant argument to method**: This case arises generally by using `this` in argument to client method. Consider splitting argument in to multiple arguments which can be mapped by database provider based on components being used in the method body.
49+
- **Other constants**: If constant is encountered in any other case then you can evaluate if constant is really needed in processing. If it is necessary to have that constant or if you cannot use solution to above cases, then create a local variable to store the value and use local variable in the query. EF Core will convert it to parameter.
5650

57-
## Client evaluation logging
51+
## Previous versions
5852

59-
By default, EF Core will log a warning when client evaluation is performed. See [Logging](../miscellaneous/logging.md) for more information on viewing logging output.
53+
The following section is applicable to EF Core versions prior to 3.0.
6054

61-
## Optional behavior: throw an exception for client evaluation
55+
EF Core supported client evaluation in any part query hence queries similar to one posted in [Unsupported client evaluation](#unsupported-client-evaluation) section worked correctly but it caused performance issue without users noticing. In order to notify users that query was being evaluated on client, EF Core logged client evaluation warning. See [Logging](xref:core/miscellaneous/logging) for more information on viewing logging output.
6256

63-
You can change the behavior when client evaluation occurs to either throw or do nothing. This is done when setting up the options for your context - typically in `DbContext.OnConfiguring`, or in `Startup.cs` if you are using ASP.NET Core.
57+
Optionally EF Core allowed to change default behavior to throw exception or do nothing when performing client evaluation except for projection (exception throwing would make it similar to the behavior in 3.0). To change the behavior you need to configure warnings while setting up the options for your context - typically in `DbContext.OnConfiguring`, or in `Startup.cs` if you are using ASP.NET Core.
6458

65-
<!-- [!code-csharp[Main](samples/core/Querying/ClientEval/ThrowOnClientEval/BloggingContext.cs?highlight=5)] -->
66-
``` csharp
59+
```csharp
6760
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
6861
{
6962
optionsBuilder

0 commit comments

Comments
 (0)