Skip to content
This repository was archived by the owner on Feb 1, 2025. It is now read-only.

Commit 750c71f

Browse files
committed
Backporting important changes from version 2. Query filters fix. Unnecessary Expression transformation.
1 parent 45cdc01 commit 750c71f

File tree

11 files changed

+313
-261
lines changed

11 files changed

+313
-261
lines changed

Source/LinqToDB.EntityFrameworkCore/ILinqToDBForEFTools.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,10 @@ public interface ILinqToDBForEFTools
6868
/// </summary>
6969
/// <param name="expression">EF.Core expression tree.</param>
7070
/// <param name="dc">LINQ To DB <see cref="IDataContext"/> instance.</param>
71+
/// <param name="ctx">Optional DbContext instance.</param>
7172
/// <param name="model">EF.Core data model instance.</param>
7273
/// <returns>Transformed expression.</returns>
73-
Expression TransformExpression(Expression expression, IDataContext dc, IModel model);
74+
Expression TransformExpression(Expression expression, IDataContext dc, DbContext ctx, IModel model);
7475

7576
/// <summary>
7677
/// Extracts <see cref="DbContext"/> instance from <see cref="IQueryable"/> object.

Source/LinqToDB.EntityFrameworkCore/Internal/LinqToDBForEFQueryProvider.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public TResult Execute<TResult>(Expression expression)
5656

5757
public System.Collections.Generic.IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression expression)
5858
{
59-
return new AsyncEnumerableAdaper<TResult>(QueryProvider.ExecuteAsync<TResult>(expression));
59+
return new AsyncEnumerableAdapter<TResult>(QueryProvider.ExecuteAsync<TResult>(expression));
6060
}
6161

6262
IAsyncEnumerable<TResult> IQueryProviderAsync.ExecuteAsync<TResult>(Expression expression)
@@ -92,11 +92,11 @@ System.Collections.Generic.IAsyncEnumerator<T> System.Collections.Generic.IAsync
9292
return ExecuteAsync<T>(Expression).GetEnumerator();
9393
}
9494

95-
class AsyncEnumerableAdaper<TEntity> : System.Collections.Generic.IAsyncEnumerable<TEntity>
95+
class AsyncEnumerableAdapter<TEntity> : System.Collections.Generic.IAsyncEnumerable<TEntity>
9696
{
9797
private IAsyncEnumerable<TEntity> AsyncEnumerable { get; }
9898

99-
public AsyncEnumerableAdaper(IAsyncEnumerable<TEntity> asyncEnumerable)
99+
public AsyncEnumerableAdapter(IAsyncEnumerable<TEntity> asyncEnumerable)
100100
{
101101
AsyncEnumerable = asyncEnumerable;
102102
}

Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.cs

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,12 @@ public static MappingSchema GetMappingSchema(IModel model,
224224
/// </summary>
225225
/// <param name="expression">EF.Core expression tree.</param>
226226
/// <param name="dc">LINQ To DB <see cref="IDataContext"/> instance.</param>
227+
/// <param name="ctx">Optional DbContext instance.</param>
227228
/// <param name="model">EF.Core data model instance.</param>
228229
/// <returns>Transformed expression.</returns>
229-
public static Expression TransformExpression(Expression expression, IDataContext dc, IModel model)
230+
public static Expression TransformExpression(Expression expression, IDataContext dc, DbContext ctx, IModel model)
230231
{
231-
return Implementation.TransformExpression(expression, dc, model);
232+
return Implementation.TransformExpression(expression, dc, ctx, model);
232233
}
233234

234235
/// <summary>
@@ -257,17 +258,17 @@ public static DataConnection CreateLinqToDbConnection(this DbContext context,
257258
{
258259
var dbTrasaction = transaction.GetDbTransaction();
259260
if (provider.IsCompatibleConnection(dbTrasaction.Connection))
260-
dc = new LinqToDBForEFToolsDataConnection(provider, dbTrasaction, context.Model, TransformExpression);
261+
dc = new LinqToDBForEFToolsDataConnection(context, provider, dbTrasaction, context.Model, TransformExpression);
261262
}
262263

263264
if (dc == null)
264265
{
265266
var dbConnection = context.Database.GetDbConnection();
266267
if (provider.IsCompatibleConnection(dbConnection))
267-
dc = new LinqToDBForEFToolsDataConnection(provider, dbConnection, context.Model, TransformExpression);
268+
dc = new LinqToDBForEFToolsDataConnection(context, provider, dbConnection, context.Model, TransformExpression);
268269
else
269270
{
270-
dc = new LinqToDBForEFToolsDataConnection(provider, connectionInfo.ConnectionString, context.Model, TransformExpression);
271+
dc = new LinqToDBForEFToolsDataConnection(context, provider, connectionInfo.ConnectionString, context.Model, TransformExpression);
271272
}
272273
}
273274

@@ -309,18 +310,18 @@ public static IDataContext CreateLinqToDbContext(this DbContext context,
309310
{
310311
var dbTransaction = transaction.GetDbTransaction();
311312
if (provider.IsCompatibleConnection(dbTransaction.Connection))
312-
dc = new LinqToDBForEFToolsDataConnection(provider, dbTransaction, context.Model, TransformExpression);
313+
dc = new LinqToDBForEFToolsDataConnection(context, provider, dbTransaction, context.Model, TransformExpression);
313314
}
314315

315316
if (dc == null)
316317
{
317318
var dbConnection = context.Database.GetDbConnection();
318319
if (provider.IsCompatibleConnection(dbConnection))
319-
dc = new LinqToDBForEFToolsDataConnection(provider, context.Database.GetDbConnection(), context.Model, TransformExpression);
320+
dc = new LinqToDBForEFToolsDataConnection(context, provider, context.Database.GetDbConnection(), context.Model, TransformExpression);
320321
else
321322
{
322323
// special case when we have to create data connection by itself
323-
var dataContext = new LinqToDBForEFToolsDataContext(provider, connectionInfo.ConnectionString, context.Model, TransformExpression);
324+
var dataContext = new LinqToDBForEFToolsDataContext(context, provider, connectionInfo.ConnectionString, context.Model, TransformExpression);
324325

325326
if (mappingSchema != null)
326327
dataContext.MappingSchema = mappingSchema;
@@ -355,7 +356,7 @@ public static DataConnection CreateLinq2DbConnectionDetached([JetBrains.Annotati
355356
var connectionInfo = GetConnectionInfo(info);
356357
var dataProvider = GetDataProvider(info, connectionInfo);
357358

358-
var dc = new LinqToDBForEFToolsDataConnection(dataProvider, connectionInfo.ConnectionString, context.Model, TransformExpression);
359+
var dc = new LinqToDBForEFToolsDataConnection(context, dataProvider, connectionInfo.ConnectionString, context.Model, TransformExpression);
359360
var logger = CreateLogger(info.Options);
360361
if (logger != null)
361362
dc.OnTraceConnection = t => Implementation.LogConnectionTrace(t, logger);
@@ -419,9 +420,9 @@ public static DataConnection CreateLinqToDbConnection(this DbContextOptions opti
419420
var model = GetModel(options);
420421

421422
if (connectionInfo.Connection != null)
422-
dc = new LinqToDBForEFToolsDataConnection(dataProvider, connectionInfo.Connection, model, TransformExpression);
423+
dc = new LinqToDBForEFToolsDataConnection(null, dataProvider, connectionInfo.Connection, model, TransformExpression);
423424
else if (connectionInfo.ConnectionString != null)
424-
dc = new LinqToDBForEFToolsDataConnection(dataProvider, connectionInfo.ConnectionString, model, TransformExpression);
425+
dc = new LinqToDBForEFToolsDataConnection(null, dataProvider, connectionInfo.ConnectionString, model, TransformExpression);
425426

426427
if (dc == null)
427428
throw new LinqToDBForEFToolsException($"Can not extract connection information from {nameof(DbContextOptions)}");
@@ -453,11 +454,7 @@ public static IQueryable<T> ToLinqToDB<T>(this IQueryable<T> query, IDataContext
453454
if (context == null)
454455
throw new LinqToDBForEFToolsException("Can not evaluate current context from query");
455456

456-
var newExpression = dc is IExpressionPreprocessor
457-
? query.Expression
458-
: TransformExpression(query.Expression, dc, context.Model);
459-
460-
return new LinqToDBForEFQueryProvider<T>(dc, newExpression);
457+
return new LinqToDBForEFQueryProvider<T>(dc, query.Expression);
461458
}
462459

463460
/// <summary>
@@ -479,11 +476,7 @@ public static IQueryable<T> ToLinqToDB<T>(this IQueryable<T> query)
479476

480477
var dc = CreateLinqToDbContext(context);
481478

482-
var newExpression = dc is IExpressionPreprocessor
483-
? query.Expression
484-
: TransformExpression(query.Expression, dc, context.Model);
485-
486-
return new LinqToDBForEFQueryProvider<T>(dc, newExpression);
479+
return new LinqToDBForEFQueryProvider<T>(dc, query.Expression);
487480
}
488481

489482
/// <summary>

Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataConnection.cs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.EntityFrameworkCore.Metadata;
66

77
using JetBrains.Annotations;
8+
using Microsoft.EntityFrameworkCore;
89

910
namespace LinqToDB.EntityFrameworkCore
1011
{
@@ -15,45 +16,52 @@ namespace LinqToDB.EntityFrameworkCore
1516

1617
public class LinqToDBForEFToolsDataConnection : DataConnection, IExpressionPreprocessor
1718
{
19+
readonly DbContext _context;
1820
readonly IModel _model;
19-
readonly Func<Expression, IDataContext, IModel, Expression> _transformFunc;
21+
readonly Func<Expression, IDataContext, DbContext, IModel, Expression> _transformFunc;
2022

2123
public LinqToDBForEFToolsDataConnection(
22-
[NotNull] IDataProvider dataProvider,
23-
[NotNull] string connectionString,
24-
IModel model,
25-
Func<Expression, IDataContext, IModel, Expression> transformFunc) : base(dataProvider, connectionString)
24+
[CanBeNull] DbContext context,
25+
[NotNull] IDataProvider dataProvider,
26+
[NotNull] string connectionString,
27+
IModel model,
28+
Func<Expression, IDataContext, DbContext, IModel, Expression> transformFunc) : base(dataProvider, connectionString)
2629
{
27-
_model = model;
30+
_context = context;
31+
_model = model;
2832
_transformFunc = transformFunc;
2933
}
3034

3135
public LinqToDBForEFToolsDataConnection(
32-
[NotNull] IDataProvider dataProvider,
33-
[NotNull] IDbTransaction transaction,
34-
IModel model,
35-
Func<Expression, IDataContext, IModel, Expression> transformFunc
36+
[CanBeNull] DbContext context,
37+
[NotNull] IDataProvider dataProvider,
38+
[NotNull] IDbTransaction transaction,
39+
IModel model,
40+
Func<Expression, IDataContext, DbContext, IModel, Expression> transformFunc
3641
) : base(dataProvider, transaction)
3742
{
38-
_model = model;
43+
_context = context;
44+
_model = model;
3945
_transformFunc = transformFunc;
4046
}
4147

4248
public LinqToDBForEFToolsDataConnection(
43-
[NotNull] IDataProvider dataProvider,
44-
[NotNull] IDbConnection connection,
45-
IModel model,
46-
Func<Expression, IDataContext, IModel, Expression> transformFunc) : base(dataProvider, connection)
49+
[CanBeNull] DbContext context,
50+
[NotNull] IDataProvider dataProvider,
51+
[NotNull] IDbConnection connection,
52+
IModel model,
53+
Func<Expression, IDataContext, DbContext, IModel, Expression> transformFunc) : base(dataProvider, connection)
4754
{
48-
_model = model;
55+
_context = context;
56+
_model = model;
4957
_transformFunc = transformFunc;
5058
}
5159

5260
public Expression ProcessExpression(Expression expression)
5361
{
5462
if (_transformFunc == null)
5563
return expression;
56-
return _transformFunc(expression, this, _model);
64+
return _transformFunc(expression, this, _context, _model);
5765
}
5866
}
5967
}

Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataContext.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Microsoft.EntityFrameworkCore.Metadata;
55

66
using JetBrains.Annotations;
7+
using Microsoft.EntityFrameworkCore;
78

89
namespace LinqToDB.EntityFrameworkCore
910
{
@@ -13,24 +14,28 @@ namespace LinqToDB.EntityFrameworkCore
1314

1415
public class LinqToDBForEFToolsDataContext : DataContext, IExpressionPreprocessor
1516
{
17+
[CanBeNull]
18+
readonly DbContext _context;
1619
readonly IModel _model;
17-
readonly Func<Expression, IDataContext, IModel, Expression> _transformFunc;
20+
readonly Func<Expression, IDataContext, DbContext, IModel, Expression> _transformFunc;
1821

1922
public LinqToDBForEFToolsDataContext(
20-
[NotNull] IDataProvider dataProvider,
21-
[NotNull] string connectionString,
22-
IModel model,
23-
Func<Expression, IDataContext, IModel, Expression> transformFunc) : base(dataProvider, connectionString)
23+
[CanBeNull] DbContext context,
24+
[NotNull] IDataProvider dataProvider,
25+
[NotNull] string connectionString,
26+
IModel model,
27+
Func<Expression, IDataContext, DbContext, IModel, Expression> transformFunc) : base(dataProvider, connectionString)
2428
{
25-
_model = model;
29+
_context = context;
30+
_model = model;
2631
_transformFunc = transformFunc;
2732
}
2833

2934
public Expression ProcessExpression(Expression expression)
3035
{
3136
if (_transformFunc == null)
3237
return expression;
33-
return _transformFunc(expression, this, _model);
38+
return _transformFunc(expression, this, _context, _model);
3439
}
3540

3641
}

Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,9 +581,10 @@ static List<Expression> CompactTree(List<Expression> items, ExpressionType nodeT
581581
/// </summary>
582582
/// <param name="expression">EF.Core expression tree.</param>
583583
/// <param name="dc">LINQ To DB <see cref="IDataContext"/> instance.</param>
584+
/// <param name="ctx">Optional DbContext instance.</param>
584585
/// <param name="model">EF.Core data model instance.</param>
585586
/// <returns>Transformed expression.</returns>
586-
public virtual Expression TransformExpression(Expression expression, IDataContext dc, IModel model)
587+
public virtual Expression TransformExpression(Expression expression, IDataContext dc, DbContext ctx, IModel model)
587588
{
588589
var ignoreQueryFilters = false;
589590

@@ -681,6 +682,24 @@ Expression LocalTransform(Expression e)
681682
if (filter != null)
682683
{
683684
var filterBody = filter.Body.Transform(l => LocalTransform(l));
685+
686+
// replacing DbContext constant
687+
if (ctx != null)
688+
{
689+
filterBody = filterBody.Transform(fe =>
690+
{
691+
if (fe.NodeType == ExpressionType.Constant)
692+
{
693+
if (fe.Type.IsAssignableFrom(ctx.GetType()))
694+
{
695+
return Expression.Constant(ctx, fe.Type);
696+
}
697+
}
698+
699+
return fe;
700+
});
701+
}
702+
684703
filter = Expression.Lambda(filterBody, filter.Parameters[0]);
685704
var whereExpr = Expression.Call(null, WhereMethodInfo.MakeGenericMethod(entityType), newExpr, Expression.Quote(filter));
686705

Source/LinqToDB.EntityFrameworkCore/linq2db.EntityFrameworkCore.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="linq2db" Version="2.9.5" />
12+
<PackageReference Include="linq2db" Version="2.9.6" />
1313
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.2.6" />
1414
</ItemGroup>
1515

Tests/LinqToDB.EntityFrameworkCore.Tests/LinqToDB.EntityFrameworkCore.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
<ItemGroup>
1414
<PackageReference Include="JetBrains.DotMemoryUnit" Version="3.0.20171219.105559" />
15-
<PackageReference Include="linq2db" Version="2.9.5" />
15+
<PackageReference Include="linq2db" Version="2.9.6" />
1616
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.2.6" />
1717
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.6" />
1818
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.2.0" />

0 commit comments

Comments
 (0)