|
| 1 | +--- |
| 2 | +Permalink: ef-core-query-deferred |
| 3 | +--- |
| 4 | + |
| 5 | +# Query Deferred |
| 6 | + |
| 7 | +> This feature is now available on [Entity Framework Classic - Query Deferred](http://entityframework-classic.net/query-deferred). Entity Framework Classic is a supported version from the latest EF6 code base. It supports .NET Framework and .NET Core and overcomes some EF limitations by adding tons of must-haves built-in features. |
| 8 | +
|
| 9 | +## Introduction |
| 10 | + |
| 11 | +There are two types of IQueryable extension methods: |
| 12 | + |
| 13 | +Deferred Methods: The query expression is modified but the query is not resolved (Select, Where, etc.). |
| 14 | +Immediate Methods: The query expression is modified and the query is resolved (Count, First, etc.). |
| 15 | +However, some third party features like **Query Cache** and **Query Future** cannot be used directly with Immediate Method since the query is already resolved. |
| 16 | + |
| 17 | +**EF+ Query Deferred** provides more flexibility to other features. |
| 18 | + |
| 19 | +{% include template-example.html %} |
| 20 | +```csharp |
| 21 | + |
| 22 | +// Oops! The query is already executed, we cannot cache it. |
| 23 | +var count = ctx.Customers.Count(); |
| 24 | + |
| 25 | +// Oops! All customers are cached instead of the customer count. |
| 26 | +var count = ctx.Customers.FromCache().Count(); |
| 27 | + |
| 28 | +``` |
| 29 | +[Try it in EF6](https://dotnetfiddle.net/WgpFfH) | [Try it in EF Core](https://dotnetfiddle.net/cu3UiE) |
| 30 | + |
| 31 | +Here comes in play the deferred query which acts exactly like deferred methods, by modifying the query expression without resolving it. |
| 32 | + |
| 33 | +{% include template-example.html %} |
| 34 | +```csharp |
| 35 | + |
| 36 | +// using Z.EntityFramework.Plus; // Don't forget to include this. |
| 37 | +var ctx = new EntitiesContext(); |
| 38 | + |
| 39 | +// The count is deferred and cached. |
| 40 | +var count = ctx.Customers.DeferredCount().FromCache(); |
| 41 | + |
| 42 | +``` |
| 43 | +[Try it in EF6](https://dotnetfiddle.net/ZChhmD) | [Try it in EF Core](https://dotnetfiddle.net/xIz5wx) |
| 44 | + |
| 45 | +#### All LINQ IQueryable extension methods and overloads are supported: |
| 46 | + |
| 47 | + - DeferredAggregate |
| 48 | + - DeferredAll |
| 49 | + - DeferredAny |
| 50 | + - DeferredAverage |
| 51 | + - DeferredContains |
| 52 | + - DeferredCount |
| 53 | + - DeferredElementAt |
| 54 | + - DeferredElementAtOrDefault |
| 55 | + - DeferredFirst |
| 56 | + - DeferredFirstOrDefault |
| 57 | + - DeferredLast |
| 58 | + - DeferredLastOrDefault |
| 59 | + - DeferredLongCount |
| 60 | + - DeferredMax |
| 61 | + - DeferredMin |
| 62 | + - DeferredSequenceEqual |
| 63 | + - DeferredSingle |
| 64 | + - DeferredSingleOrDefault |
| 65 | + - DeferredSum |
| 66 | + |
| 67 | +## EF+ Query Deferred |
| 68 | + |
| 69 | +Defer the execution of a query which is normally executed to allow some features like Query Cache and Query Future. |
| 70 | + |
| 71 | +{% include template-example.html %} |
| 72 | +```csharp |
| 73 | + |
| 74 | +// using Z.EntityFramework.Plus; // Don't forget to include this. |
| 75 | +var ctx = new EntitiesContext(); |
| 76 | + |
| 77 | +// Query Cache |
| 78 | +ctx.Customers.DeferredCount().FromCache(); |
| 79 | + |
| 80 | +// Query Future |
| 81 | +ctx.Customers.DeferredCount().FutureValue(); |
| 82 | + |
| 83 | +``` |
| 84 | +[Try it in EF6](https://dotnetfiddle.net/5KcNj3) | [Try it in EF Core](https://dotnetfiddle.net/ohLJL3) |
| 85 | + |
| 86 | +## EF+ Query Deferred Execute |
| 87 | + |
| 88 | +Execute the deferred query and return the result. |
| 89 | + |
| 90 | +{% include template-example.html %} |
| 91 | +```csharp |
| 92 | + |
| 93 | +// using Z.EntityFramework.Plus; // Don't forget to include this. |
| 94 | +var ctx = new EntitiesContext(); |
| 95 | + |
| 96 | +var countDeferred = ctx.Customers.DeferredCount(); |
| 97 | +var count = countDeferred.Execute(); |
| 98 | + |
| 99 | +``` |
| 100 | +[Try it in EF6](https://dotnetfiddle.net/sXOfNB) | [Try it in EF Core](https://dotnetfiddle.net/Ou2Ly4) |
| 101 | + |
| 102 | +## EF+ Query Deferred Execute Async |
| 103 | + |
| 104 | +Execute the Deferred query asynchronously and return the result. |
| 105 | + |
| 106 | +**ExecuteAsync** methods are available starting from .NET Framework 4.5 and support all the same options than **Execute** methods. |
| 107 | + |
| 108 | +{% include template-example.html %} |
| 109 | +```csharp |
| 110 | + |
| 111 | +// using Z.EntityFramework.Plus; // Don't forget to include this. |
| 112 | +var ctx = new EntitiesContext(); |
| 113 | + |
| 114 | +var countDeferred = ctx.Customers.DeferredCount(); |
| 115 | +var taskCount = countDeferred.ExecuteAsync(); |
| 116 | + |
| 117 | +``` |
| 118 | +[Try it in EF6](https://dotnetfiddle.net/0BpVn1) | [Try it in EF Core](https://dotnetfiddle.net/1pttmj) |
| 119 | + |
| 120 | +## Real Life Scenarios |
| 121 | + |
| 122 | +EF Query Deferred brings advantages to other third party features: |
| 123 | + |
| 124 | + - Allows to use Immediate Method with EF+ Query Cache. |
| 125 | + - Allows to use Immediate Method with EF+ Query Future. |
| 126 | + - Allows to use Immediate Method with YOUR own features. |
| 127 | + |
| 128 | +## Behind the code |
| 129 | +When a deferred method is used, the query expression is created exactly like a non-deferred method but instead of invoking the execute method from the query provider, a new instance of a class QueryDeferred<TResult> is created using the query and the expression. |
| 130 | + |
| 131 | +The QueryDeferred instance has methods to either execute the expression from the query provider or let a third party library use the object query. |
| 132 | + |
| 133 | +## Limitations |
| 134 | + |
| 135 | +None. |
| 136 | + |
| 137 | +## Requirements |
| 138 | + |
| 139 | + - **EF+ Query Deferred:** Full version or Standalone version |
| 140 | + - **Database Provider:** All supported |
| 141 | + - **Entity Framework Version:** EF5, EF6, EF Core |
| 142 | + - **Minimum Framework Version:** .NET Framework 4 |
| 143 | + |
| 144 | +## Conclusion |
| 145 | + |
| 146 | +As we saw, EF+ **Query Deferred** brings considerable advantages to other libraries by letting them use immediate methods without removing any of their features. |
| 147 | + |
| 148 | +Need help getting started? [[email protected]](mailto:[email protected]) |
| 149 | + |
| 150 | +We welcome all comments, ideas and suggestions to improve our library. |
0 commit comments