You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: entity-framework/core/performance/advanced-performance-topics.md
+21-10
Original file line number
Diff line number
Diff line change
@@ -153,26 +153,37 @@ Note that there is no need to parameterize each and every query: it's perfectly
153
153
154
154
In some situations, it is necessary to dynamically construct LINQ queries rather than specifying them outright in source code. This can happen, for example, in a website which receives arbitrary query details from a client, with open-ended query operators (sorting, filtering, paging...). In principle, if done correctly, dynamically-constructed queries can be just as efficient as regular ones (although it's not possible to use the compiled query optimization with dynamic queries). In practice, however, they are frequently the source of performance issues, since it's easy to accidentally produce expression trees with shapes that differ every time.
155
155
156
-
The following example uses two techniques to dynamically construct a query; we add a `Where`operator to the query only if the given parameter is not null. Note that this isn't a good use case for dynamically constructing a query - but we're using it for simplicity:
156
+
The following example uses three techniques to construct a query's `Where`lambda expression:
157
157
158
-
### [With constant](#tab/with-constant)
158
+
1.**Expression API with constant**: Dynamically build the expression with the Expression API, using a constant node. This is a frequent mistake when dynamically building expression trees, and causes EF to recompile the query each time it's invoked with a different constant value (it also usually causes plan cache pollution at the database server).
159
+
2.**Expression API with parameter**: A better version, which substitutes the constant with a parameter. This ensures that the query is only compiled once regardless of the value provided, and the same (parameterized) SQL is generated.
160
+
3.**Simple with parameter**: A version which doesn't use the Expression API, for comparison, which creates the same tree as the method above but is much simpler. In many cases, it's possible to dynamically build your expression tree without resorting to the Expression API, which is easy to get wrong.
; we add a `Where` operator to the query only if the given parameter is not null. Note that this isn't a good use case for dynamically constructing a query - but we're using it for simplicity:
161
163
162
-
### [With parameter](#tab/with-parameter)
164
+
### [Expression API with constant](#tab/expression-api-with-constant)
| ExpressionApiWithConstant | 1,665.8 us | 56.99 us | 163.5 us | 15.6250 | - | 109.92 KB |
183
+
| ExpressionApiWithParameter | 757.1 us | 35.14 us | 103.6 us | 12.6953 | 0.9766 | 54.95 KB |
184
+
| SimpleWithParameter | 760.3 us | 37.99 us | 112.0 us | 12.6953 | - | 55.03 KB |
174
185
175
-
Even if the sub-millisecond difference seems small, keep in mind that the constant version continuously pollutes the cache and causes other queries to be re-compiled, slowing them down as well.
186
+
Even if the sub-millisecond difference seems small, keep in mind that the constant version continuously pollutes the cache and causes other queries to be re-compiled, slowing them down as well and having a general negative impact on your overall performance. It's highly recommended to avoid constant query recompilation.
176
187
177
188
> [!NOTE]
178
189
> Avoid constructing queries with the expression tree API unless you really need to. Aside from the API's complexity, it's very easy to inadvertently cause significant performance issues when using them.
0 commit comments