Skip to content

Commit f151e37

Browse files
Fix EF Core Preview5
Fix EF Core Preview5
1 parent 3d115f0 commit f151e37

File tree

10 files changed

+156
-52
lines changed

10 files changed

+156
-52
lines changed

src/shared/Z.EF.Plus.QueryDeferred.Shared/QueryDeferred.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,18 @@ public QueryDeferred(IQueryable query, Expression expression)
4848
var createQueryMethod = provider.GetType().GetMethod("CreateQuery", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(Expression), typeof(Type) }, null);
4949
Query = (IQueryable<TResult>)createQueryMethod.Invoke(provider, new object[] { expression, typeof(TResult) });
5050
#elif EFCORE
51-
Query = new EntityQueryable<TResult>((IAsyncQueryProvider)query.Provider);
52-
var expressionProperty = typeof(QueryableBase<>).MakeGenericType(typeof(TResult)).GetProperty("Expression", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
53-
expressionProperty.SetValue(Query, expression);
51+
if (EFCoreHelper.IsVersion3x)
52+
{
53+
// EF Core 3.x
54+
Query = new EntityQueryable<TResult>((IAsyncQueryProvider)query.Provider, Expression);
55+
}
56+
else
57+
{
58+
// EF Core 2.x
59+
Query = new EntityQueryable<TResult>((IAsyncQueryProvider)query.Provider);
60+
var expressionProperty = typeof(QueryableBase<>).MakeGenericType(typeof(TResult)).GetProperty("Expression", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
61+
expressionProperty.SetValue((QueryableBase<TResult>)Query, expression);
62+
}
5463
#endif
5564
}
5665

src/shared/Z.EF.Plus.QueryFuture.Shared/BaseQueryFuture.cs

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
using Remotion.Linq.Parsing.Structure;
3737
using Microsoft.EntityFrameworkCore.Query.Expressions;
3838
using Remotion.Linq.Clauses;
39+
using Microsoft.EntityFrameworkCore.Query.Sql;
3940

4041
#endif
4142

@@ -90,6 +91,9 @@ public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQuer
9091
{
9192
bool isEFCore2x = false;
9293
bool EFCore_2_1 = false;
94+
#if EFCORE
95+
bool isEFCore3x = EFCoreHelper.IsVersion3x;
96+
#endif
9397

9498
var context = Query.GetDbContext();
9599

@@ -155,7 +159,11 @@ public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQuer
155159
#if NETSTANDARD2_0
156160
IEvaluatableExpressionFilter evaluatableExpressionFilter = null;
157161

158-
if (EFCore_2_1)
162+
if (isEFCore3x)
163+
{
164+
evaluatableExpressionFilter = (RelationalEvaluatableExpressionFilter)QueryModelGenerator.GetType().GetProperty("EvaluatableExpressionFilter", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(QueryModelGenerator);
165+
}
166+
else if (EFCore_2_1)
159167
{
160168
evaluatableExpressionFilter = (IEvaluatableExpressionFilter)QueryModelGenerator.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(QueryModelGenerator);
161169
}
@@ -226,7 +234,15 @@ public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQuer
226234
var innerConnectionField = typeof(RelationalConnection).GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance);
227235
var initalConnection = innerConnectionField.GetValue(QueryConnection);
228236

229-
innerConnectionField.SetValue(QueryConnection, new Microsoft.EntityFrameworkCore.Internal.LazyRef<DbConnection>(() => innerConnection));
237+
if (EFCoreHelper.IsVersion3xPreview5)
238+
{
239+
innerConnectionField.SetValue(QueryConnection, innerConnection);
240+
}
241+
else
242+
{
243+
innerConnectionField.SetValue(QueryConnection, LazyHelper.NewLazy<DbConnection>(() => innerConnection));
244+
}
245+
230246

231247
RestoreConnection = () => innerConnectionField.SetValue(QueryConnection, initalConnection);
232248
}
@@ -244,7 +260,7 @@ public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQuer
244260
var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
245261
var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory);
246262

247-
var lazyRefStateManager = new LazyRef<IStateManager>(() => stateManager);
263+
var lazyRefStateManager = LazyHelper.NewLazy(() => stateManager);
248264

249265
queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { createQueryBufferDelegate, QueryConnection, lazyRefStateManager, concurrencyDetector, executionStrategyFactory });
250266
}
@@ -254,7 +270,7 @@ public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQuer
254270
var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
255271
var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory);
256272

257-
var lazyRefStateManager = new LazyRef<IStateManager>(() => stateManager);
273+
var lazyRefStateManager = LazyHelper.NewLazy(() => stateManager);
258274

259275
var dependenciesProperty3 = typeof(RelationalQueryContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance);
260276
var dependencies3 = dependenciesProperty3.GetValue(queryContextFactory);
@@ -270,8 +286,16 @@ public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQuer
270286

271287
Expression newQuery;
272288

289+
if (isEFCore3x)
290+
{
291+
var parameterExtractingExpressionVisitorConstructor = typeof(ParameterExtractingExpressionVisitor).GetConstructors().First(x => x.GetParameters().Length == 6);
273292

274-
if(isEFCore2x)
293+
var parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, queryContext.GetType(), logger, true, false });
294+
295+
// CREATE new query from query visitor
296+
newQuery = parameterExtractingExpressionVisitor.ExtractParameters(Query.Expression);
297+
}
298+
else if(isEFCore2x)
275299
{
276300
var parameterExtractingExpressionVisitorConstructors = typeof(ParameterExtractingExpressionVisitor).GetConstructors();
277301

@@ -289,10 +313,9 @@ public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQuer
289313

290314
var parameterExtractingExpressionVisitorConstructor = parameterExtractingExpressionVisitorConstructors.First(x => x.GetParameters().Length == 6);
291315

292-
ParameterExtractingExpressionVisitor parameterExtractingExpressionVisitor = null;
316+
ParameterExtractingExpressionVisitor parameterExtractingExpressionVisitor = null;
293317

294-
// EF Core 2.1
295-
if (parameterExtractingExpressionVisitorConstructor.GetParameters().Where(x => x.ParameterType == typeof(DbContext)).Any())
318+
if (parameterExtractingExpressionVisitorConstructor.GetParameters().Where(x => x.ParameterType == typeof(DbContext)).Any())
296319
{
297320
parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, logger, context, true, false });
298321
}
@@ -346,14 +369,33 @@ public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQuer
346369
sqlQuery = queryModelVisitor.Queries.First();
347370
}
348371

349-
// RETURN the IRealationCommand
372+
// RETURN the IRelationalCommand
373+
#if EFCORE
374+
IRelationalCommand relationalCommand = null;
375+
var dynamicSqlGenerator = (dynamic)sqlQuery.CreateDefaultQuerySqlGenerator();
376+
377+
if (isEFCore3x)
378+
{
379+
var commandBuilderFactory = context.Database.GetService<IRelationalCommandBuilderFactory>();
380+
381+
// TODO: Fix null for DbLogger
382+
relationalCommand = (IRelationalCommand)dynamicSqlGenerator.GenerateSql(commandBuilderFactory, queryContext.ParameterValues, null);
383+
}
384+
else
385+
{
386+
relationalCommand = (IRelationalCommand)dynamicSqlGenerator.GenerateSql(queryContext.ParameterValues);
387+
}
388+
389+
#else
350390
var relationalCommand = sqlQuery.CreateDefaultQuerySqlGenerator().GenerateSql(queryContext.ParameterValues);
391+
#endif
392+
351393
return relationalCommand;
352394
}
353395
#endif
354396

355-
/// <summary>Sets the result of the query deferred.</summary>
356-
/// <param name="reader">The reader returned from the query execution.</param>
397+
/// <summary>Sets the result of the query deferred.</summary>
398+
/// <param name="reader">The reader returned from the query execution.</param>
357399
public virtual void SetResult(DbDataReader reader)
358400
{
359401
}

src/shared/Z.EF.Plus._Core.Shared/EF/DbContext/DbContext.MapReader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ internal static IEnumerable<T> MapReader<T>(this DbContext context, DbDataReader
149149
// REFLECTION: Query.Provider._queryCompiler._queryContextFactory.ExecutionStrategyFactory
150150
var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
151151
var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory);
152-
153-
var lazyRefStateManager = new LazyRef<IStateManager>(() => stateManager);
152+
153+
var lazyRefStateManager = LazyHelper.NewLazy(() => stateManager);
154154

155155
queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { createQueryBufferDelegate, connection, lazyRefStateManager, concurrencyDetector, executionStrategyFactory });
156156
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Description: Entity Framework Bulk Operations & Utilities (EF Bulk SaveChanges, Insert, Update, Delete, Merge | LINQ Query Cache, Deferred, Filter, IncludeFilter, IncludeOptimize | Audit)
2+
// Website & Documentation: https://github.com/zzzprojects/Entity-Framework-Plus
3+
// Forum & Issues: https://github.com/zzzprojects/EntityFramework-Plus/issues
4+
// License: https://github.com/zzzprojects/EntityFramework-Plus/blob/master/LICENSE
5+
// More projects: http://www.zzzprojects.com/
6+
// Copyright © ZZZ Projects Inc. 2014 - 2016. All rights reserved.
7+
8+
#if EFCORE
9+
using Microsoft.EntityFrameworkCore;
10+
using Microsoft.EntityFrameworkCore.Query.Sql;
11+
namespace Z.EntityFramework.Plus
12+
{
13+
internal static partial class EFCoreHelper
14+
{
15+
internal static bool IsVersion3x = typeof(IQuerySqlGenerator).GetMethod("GenerateSql").GetParameters().Length == 3;
16+
internal static bool IsVersion3xPreview5 = IsVersion3x && typeof(DbContext).Assembly.GetType("Microsoft.EntityFrameworkCore.Internal.LazyRef`1") == null;
17+
}
18+
}
19+
#endif

src/shared/Z.EF.Plus._Core.Shared/EFCore/IQueryable`/CreateCommand.cs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Microsoft.EntityFrameworkCore.Query;
1616
using Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal;
1717
using Microsoft.EntityFrameworkCore.Query.Internal;
18+
using Microsoft.EntityFrameworkCore.Query.Sql;
1819
using Microsoft.EntityFrameworkCore.Storage;
1920
using Remotion.Linq.Parsing.ExpressionVisitors.TreeEvaluation;
2021
using Remotion.Linq.Parsing.Structure;
@@ -117,6 +118,9 @@ public static IRelationalCommand CreateCommand<T>(this IQueryable<T> source, out
117118
public static IRelationalCommand CreateCommand(this IQueryable source, out RelationalQueryContext queryContext)
118119
{
119120
bool EFCore_2_1 = false;
121+
#if EFCORE
122+
bool isEFCore3x = EFCoreHelper.IsVersion3x;
123+
#endif
120124

121125
var compilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance);
122126
var compiler = compilerField.GetValue(source.Provider);
@@ -158,14 +162,18 @@ public static IRelationalCommand CreateCommand(this IQueryable source, out Relat
158162
#if NETSTANDARD2_0
159163
IEvaluatableExpressionFilter evaluatableExpressionFilter = null;
160164

161-
if (EFCore_2_1)
165+
if (isEFCore3x)
166+
{
167+
evaluatableExpressionFilter = (RelationalEvaluatableExpressionFilter)QueryModelGenerator.GetType().GetProperty("EvaluatableExpressionFilter", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(QueryModelGenerator);
168+
}
169+
else if (EFCore_2_1)
162170
{
163171
evaluatableExpressionFilter = (IEvaluatableExpressionFilter)QueryModelGenerator.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(QueryModelGenerator);
164172
}
165-
else
166-
{
167-
evaluatableExpressionFilter = (IEvaluatableExpressionFilter)compiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(queryCompiler);
168-
}
173+
else
174+
{
175+
evaluatableExpressionFilter = (IEvaluatableExpressionFilter) compiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(queryCompiler);
176+
}
169177
#else
170178
var evalutableExpressionFilterField = compiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static);
171179
var evalutableExpressionFilter = (IEvaluatableExpressionFilter)evalutableExpressionFilterField.GetValue(null);
@@ -197,7 +205,16 @@ public static IRelationalCommand CreateCommand(this IQueryable source, out Relat
197205

198206
var parameterExtractingExpressionVisitorConstructors = typeof(ParameterExtractingExpressionVisitor).GetConstructors();
199207

200-
if (parameterExtractingExpressionVisitorConstructors.Any(x => x.GetParameters().Length == 5))
208+
if (isEFCore3x)
209+
{
210+
var parameterExtractingExpressionVisitorConstructor = typeof(ParameterExtractingExpressionVisitor).GetConstructors().First(x => x.GetParameters().Length == 6);
211+
212+
var parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, queryContext.GetType(), logger, true, false });
213+
214+
// CREATE new query from query visitor
215+
newQuery = parameterExtractingExpressionVisitor.ExtractParameters(source.Expression);
216+
}
217+
else if (parameterExtractingExpressionVisitorConstructors.Any(x => x.GetParameters().Length == 5))
201218
{
202219
// EF Core 2.1
203220
var parameterExtractingExpressionVisitorConstructor = parameterExtractingExpressionVisitorConstructors.First(x => x.GetParameters().Length == 5);
@@ -273,10 +290,21 @@ public static IRelationalCommand CreateCommand(this IQueryable source, out Relat
273290
var queries = queryModelVisitor.Queries;
274291
var sqlQuery = queries.ToList()[0];
275292

293+
IRelationalCommand relationalCommand = null;
294+
var dynamicSqlGenerator = (dynamic)sqlQuery.CreateDefaultQuerySqlGenerator();
276295

277-
var command = sqlQuery.CreateDefaultQuerySqlGenerator().GenerateSql(queryContext.ParameterValues);
296+
if (isEFCore3x)
297+
{
298+
var commandBuilderFactory = queryContext.Context.Database.GetService<IRelationalCommandBuilderFactory>();
299+
// TODO: Fix null for DbLogger
300+
relationalCommand = (IRelationalCommand)dynamicSqlGenerator.GenerateSql(commandBuilderFactory, queryContext.ParameterValues, null);
301+
}
302+
else
303+
{
304+
relationalCommand = (IRelationalCommand)dynamicSqlGenerator.GenerateSql(queryContext.ParameterValues);
305+
}
278306

279-
return command;
307+
return relationalCommand;
280308
}
281309
}
282310
}

src/shared/Z.EF.Plus._Core.Shared/EFCore/IQueryable`/GetDbContext.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,6 @@ public static DbContext GetDbContext<T>(this IQueryable<T> source)
4848

4949
IStateManager stateManager = stateManagerDynamic as IStateManager;
5050

51-
if (stateManager == null)
52-
{
53-
Microsoft.EntityFrameworkCore.Internal.LazyRef<IStateManager> lazyStateManager = stateManagerDynamic as Microsoft.EntityFrameworkCore.Internal.LazyRef<IStateManager>;
54-
if(lazyStateManager != null)
55-
{
56-
stateManager = lazyStateManager.Value;
57-
}
58-
}
59-
6051
if (stateManager == null)
6152
{
6253
stateManager = ((dynamic) stateManagerDynamic).Value;
@@ -101,15 +92,6 @@ public static DbContext GetDbContext(this IQueryable query)
10192

10293
IStateManager stateManager = stateManagerDynamic as IStateManager;
10394

104-
if (stateManager == null)
105-
{
106-
Microsoft.EntityFrameworkCore.Internal.LazyRef<IStateManager> lazyStateManager = stateManagerDynamic as Microsoft.EntityFrameworkCore.Internal.LazyRef<IStateManager>;
107-
if(lazyStateManager != null)
108-
{
109-
stateManager = lazyStateManager.Value;
110-
}
111-
}
112-
11395
if (stateManager == null)
11496
{
11597
stateManager = ((dynamic) stateManagerDynamic).Value;

src/shared/Z.EF.Plus._Core.Shared/EFCore/IQueryable`/GetInMemoryContext.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ public static DbContext GetInMemoryContext<T>(this IQueryable<T> source)
4646

4747
IStateManager stateManager = stateManagerDynamic as IStateManager;
4848

49-
if (stateManager == null)
50-
{
51-
Microsoft.EntityFrameworkCore.Internal.LazyRef<IStateManager> lazyStateManager = stateManagerDynamic as Microsoft.EntityFrameworkCore.Internal.LazyRef<IStateManager>;
52-
if (lazyStateManager != null)
53-
{
54-
stateManager = lazyStateManager.Value;
55-
}
56-
}
57-
5849
if (stateManager == null)
5950
{
6051
stateManager = ((dynamic)stateManagerDynamic).Value;

src/shared/Z.EF.Plus._Core.Shared/EFCore/IQueryable`/IQueryable`.GetCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public static IRelationalCommand GetDbCommand<T>(this IQueryable<T> query)
127127
var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
128128
var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory);
129129

130-
var lazyRefStateManager = new LazyRef<IStateManager>(() => stateManager);
130+
var lazyRefStateManager = LazyHelper.NewLazy(() => stateManager);
131131

132132
queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { createQueryBufferDelegate, connection, lazyRefStateManager, concurrencyDetector, executionStrategyFactory });
133133
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#if EFCORE
2+
using Microsoft.EntityFrameworkCore;
3+
using System;
4+
using Microsoft.EntityFrameworkCore.Internal;
5+
6+
namespace Z.EntityFramework.Plus
7+
{
8+
public class LazyHelper
9+
{
10+
public static object NewLazy<T>(Func<T> valueFactory)
11+
{
12+
if (!EFCoreHelper.IsVersion3xPreview5)
13+
{
14+
return LazyRefHelper.NewLazy<T>(valueFactory);
15+
}
16+
else
17+
{
18+
return new Lazy<T>(valueFactory);
19+
}
20+
}
21+
}
22+
23+
public class LazyRefHelper
24+
{
25+
public static object NewLazy<T>(Func<T> valueFactory)
26+
{
27+
return new LazyRef<T>(valueFactory);
28+
}
29+
}
30+
}
31+
#endif

0 commit comments

Comments
 (0)