6
6
#if ! ( NET35 || NOEF || NOASYNCPROVIDER )
7
7
using System . Threading ;
8
8
using System . Threading . Tasks ;
9
+ using System . Reflection ;
9
10
#if EFCORE
10
11
using Microsoft . EntityFrameworkCore ;
11
12
using Microsoft . EntityFrameworkCore . Query ;
@@ -34,15 +35,22 @@ public class ExpandableQuery<T> : IQueryable<T>, IOrderedQueryable<T>, IOrderedQ
34
35
public class ExpandableQuery< T > : IQueryable < T > , IOrderedQueryable < T > , IOrderedQueryable , IDbAsyncEnumerable < T >
35
36
#endif
36
37
{
37
- readonly ExpandableQueryProvider < T > _provider ;
38
+ readonly IQueryProvider _provider ;
38
39
readonly IQueryable < T > _inner ;
39
40
40
41
internal IQueryable < T > InnerQuery => _inner ; // Original query, that we're wrapping
41
42
42
43
internal ExpandableQuery ( IQueryable < T > inner , Func < Expression , Expression > queryOptimizer )
43
44
{
44
45
_inner = inner ;
45
- _provider = new ExpandableQueryProvider < T > ( this , queryOptimizer ) ;
46
+ #if EFCORE
47
+ var queryCompiler = GetQueryCompiler ( inner ) ;
48
+ #endif
49
+ _provider =
50
+ #if EFCORE
51
+ queryCompiler != null ? ( IQueryProvider ) new ExpandableIncludableQueryProvider < T > ( this , queryOptimizer , queryCompiler ) :
52
+ #endif
53
+ new ExpandableQueryProvider < T > ( this , queryOptimizer ) ;
46
54
}
47
55
48
56
Expression IQueryable . Expression => _inner . Expression ;
@@ -107,6 +115,21 @@ IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
107
115
return GetAsyncEnumerator ( ) ;
108
116
}
109
117
#endif
118
+ #endif
119
+
120
+ #if EFCORE
121
+ private static IQueryCompiler GetQueryCompiler ( IQueryable < T > query )
122
+ {
123
+ if ( query is ExpandableQuery < T > expandableQuery )
124
+ {
125
+ return GetQueryCompiler ( expandableQuery . InnerQuery ) ;
126
+ }
127
+ if ( query . Provider is EntityQueryProvider )
128
+ {
129
+ return ( IQueryCompiler ) typeof ( EntityQueryProvider ) . GetField ( "_queryCompiler" , BindingFlags . Instance | BindingFlags . NonPublic ) . GetValue ( query . Provider ) ;
130
+ }
131
+ return null ;
132
+ }
110
133
#endif
111
134
}
112
135
@@ -132,6 +155,31 @@ public IQueryable<T> Include(string path)
132
155
}
133
156
#endif
134
157
158
+ #if EFCORE
159
+ class ExpandableIncludableQueryProvider < T > : EntityQueryProvider
160
+ {
161
+ private readonly IAsyncQueryProvider _innerProvider ;
162
+
163
+ internal ExpandableIncludableQueryProvider ( ExpandableQuery < T > query , Func < Expression , Expression > queryOptimizer , IQueryCompiler queryCompiler )
164
+ : base ( queryCompiler )
165
+ {
166
+ _innerProvider = new ExpandableQueryProvider < T > ( query , queryOptimizer ) ;
167
+ }
168
+
169
+ public override IQueryable CreateQuery ( Expression expression ) => _innerProvider . CreateQuery ( expression ) ;
170
+ public override IQueryable < TElement > CreateQuery < TElement > ( Expression expression ) => _innerProvider . CreateQuery < TElement > ( expression ) ;
171
+ public override object Execute ( Expression expression ) => _innerProvider . Execute ( expression ) ;
172
+ public override TResult Execute < TResult > ( Expression expression ) => _innerProvider . Execute < TResult > ( expression ) ;
173
+
174
+ #if EFCORE3
175
+ public override TResult ExecuteAsync < TResult > ( Expression expression , CancellationToken cancellationToken = default ) => _innerProvider . ExecuteAsync < TResult > ( expression , cancellationToken ) ;
176
+ #else
177
+ public override IAsyncEnumerable < TResult > ExecuteAsync < TResult > ( Expression expression ) => _innerProvider . ExecuteAsync < TResult > ( expression ) ;
178
+ public override Task < TResult > ExecuteAsync < TResult > ( Expression expression , CancellationToken cancellationToken ) => _innerProvider . ExecuteAsync < TResult > ( expression , cancellationToken ) ;
179
+ #endif
180
+ }
181
+ #endif
182
+
135
183
class ExpandableQueryProvider < T > : IQueryProvider
136
184
#if ( NET35 || NOEF || NOASYNCPROVIDER )
137
185
#elif EFCORE
0 commit comments