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

Commit a1c05c0

Browse files
committed
Fixed members mapping.
1 parent 3a273bc commit a1c05c0

15 files changed

+511
-85
lines changed

Source/LinqToDB.EntityFrameworkCore/EFCoreMetadataReader.cs

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,22 @@
44
using System.Linq;
55
using System.Linq.Expressions;
66
using System.Reflection;
7-
using LinqToDB.Common;
8-
using LinqToDB.EntityFrameworkCore.Internal;
9-
using LinqToDB.SqlQuery;
107
using Microsoft.EntityFrameworkCore;
11-
using Microsoft.EntityFrameworkCore.Internal;
128
using Microsoft.EntityFrameworkCore.Metadata;
139
using Microsoft.EntityFrameworkCore.Metadata.Internal;
1410
using Microsoft.EntityFrameworkCore.Query;
1511
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
12+
using Microsoft.EntityFrameworkCore.Storage;
1613

1714
namespace LinqToDB.EntityFrameworkCore
1815
{
1916
using Mapping;
2017
using Metadata;
2118
using Extensions;
19+
using Common;
20+
using Internal;
21+
using SqlQuery;
22+
using SqlExpression = Microsoft.EntityFrameworkCore.Query.SqlExpressions.SqlExpression;
2223

2324
/// <summary>
2425
/// LINQ To DB metadata reader for EF.Core model.
@@ -27,12 +28,14 @@ internal class EFCoreMetadataReader : IMetadataReader
2728
{
2829
readonly IModel _model;
2930
private readonly RelationalSqlTranslatingExpressionVisitorDependencies _dependencies;
31+
private readonly IRelationalTypeMappingSource _mappingSource;
3032
private readonly ConcurrentDictionary<MemberInfo, EFCoreExpressionAttribute> _calculatedExtensions = new ConcurrentDictionary<MemberInfo, EFCoreExpressionAttribute>();
3133

32-
public EFCoreMetadataReader(IModel model, RelationalSqlTranslatingExpressionVisitorDependencies dependencies)
34+
public EFCoreMetadataReader(IModel model, RelationalSqlTranslatingExpressionVisitorDependencies dependencies, IRelationalTypeMappingSource mappingSource)
3335
{
3436
_model = model;
3537
_dependencies = dependencies;
38+
_mappingSource = mappingSource;
3639
}
3740

3841
public T[] GetAttributes<T>(Type type, bool inherit = true) where T : Attribute
@@ -189,6 +192,21 @@ public T[] GetAttributes<T>(Type type, MemberInfo memberInfo, bool inherit = tru
189192
return Array.Empty<T>();
190193
}
191194

195+
class SqlTransparentExpression : SqlExpression
196+
{
197+
public Expression Expression { get; }
198+
199+
public SqlTransparentExpression(Expression expression, RelationalTypeMapping typeMapping) : base(expression.Type, typeMapping)
200+
{
201+
Expression = expression;
202+
}
203+
204+
public override void Print(ExpressionPrinter expressionPrinter)
205+
{
206+
expressionPrinter.Print(Expression);
207+
}
208+
}
209+
192210
private Sql.ExpressionAttribute GetDbFunctionFromMethodCall(Type type, MethodInfo methodInfo)
193211
{
194212
if (_dependencies == null || _model == null)
@@ -202,22 +220,22 @@ private Sql.ExpressionAttribute GetDbFunctionFromMethodCall(Type type, MethodInf
202220

203221
if (!methodInfo.IsGenericMethodDefinition && !mi.GetCustomAttributes<Sql.ExpressionAttribute>().Any())
204222
{
205-
var objExpr = Expression.Constant(DefaultValue.GetValue(type), type);
223+
var objExpr = new SqlTransparentExpression(Expression.Constant(DefaultValue.GetValue(type), type), _mappingSource.FindMapping(type));
206224
var parameterInfos = methodInfo.GetParameters();
207225
var parametersArray = parameterInfos
208226
.Select(p =>
209-
(Expression) Expression.Constant(DefaultValue.GetValue(p.ParameterType), p.ParameterType)).ToArray();
210-
211-
var mcExpr = Expression.Call(methodInfo.IsStatic ? null : objExpr, methodInfo, parametersArray);
212-
213-
// var newExpression = _dependencies.MethodCallTranslatorProvider.Translate(_model, null, mcExpr, new List<SqlExpression>());
214-
// if (newExpression != null && newExpression != mcExpr)
215-
// {
216-
// if (!methodInfo.IsStatic)
217-
// parametersArray = new Expression[] { objExpr }.Concat(parametersArray).ToArray();
218-
//
219-
// result = ConvertToExpressionAttribute(methodInfo, newExpression, parametersArray);
220-
// }
227+
(SqlExpression)new SqlTransparentExpression(
228+
Expression.Constant(DefaultValue.GetValue(p.ParameterType), p.ParameterType),
229+
_mappingSource.FindMapping(p.ParameterType))).ToArray();
230+
231+
var newExpression = _dependencies.MethodCallTranslatorProvider.Translate(_model, objExpr, methodInfo, parametersArray);
232+
if (newExpression != null)
233+
{
234+
if (!methodInfo.IsStatic)
235+
parametersArray = new SqlExpression[] { objExpr }.Concat(parametersArray).ToArray();
236+
237+
result = ConvertToExpressionAttribute(methodInfo, newExpression, parametersArray);
238+
}
221239
}
222240

223241
return result;
@@ -239,15 +257,14 @@ private Sql.ExpressionAttribute GetDbFunctionFromProperty(Type type, PropertyInf
239257

240258
if ((propInfo.GetMethod?.IsStatic != true) && !mi.GetCustomAttributes<Sql.ExpressionAttribute>().Any())
241259
{
242-
var objExpr = Expression.Constant(DefaultValue.GetValue(type), type);
243-
var mcExpr = Expression.MakeMemberAccess(objExpr, propInfo);
244-
245-
// var newExpression = _dependencies.MemberTranslator.Translate(mcExpr);
246-
// if (newExpression != null && newExpression != mcExpr)
247-
// {
248-
// var parametersArray = new Expression[] { objExpr };
249-
// result = ConvertToExpressionAttribute(propInfo, newExpression, parametersArray);
250-
// }
260+
var objExpr = new SqlTransparentExpression(Expression.Constant(DefaultValue.GetValue(type), type), _mappingSource.FindMapping(propInfo));
261+
262+
var newExpression = _dependencies.MemberTranslatorProvider.Translate(objExpr, propInfo, propInfo.GetMemberType());
263+
if (newExpression != null)
264+
{
265+
var parametersArray = new Expression[] { objExpr };
266+
result = ConvertToExpressionAttribute(propInfo, newExpression, parametersArray);
267+
}
251268
}
252269

253270
return result;
@@ -260,7 +277,7 @@ private static EFCoreExpressionAttribute ConvertToExpressionAttribute(MemberInfo
260277
{
261278
string PrepareExpressionText(Expression expr)
262279
{
263-
var idx = parameters.IndexOf(expr);
280+
var idx = Array.IndexOf(parameters, expr);
264281
if (idx >= 0)
265282
return $"{{{idx}}}";
266283

Source/LinqToDB.EntityFrameworkCore/ILinqToDBForEFTools.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.EntityFrameworkCore.Infrastructure;
66
using Microsoft.EntityFrameworkCore.Metadata;
77
using Microsoft.EntityFrameworkCore.Query;
8+
using Microsoft.EntityFrameworkCore.Storage;
89
using Microsoft.Extensions.Logging;
910

1011
namespace LinqToDB.EntityFrameworkCore
@@ -37,8 +38,9 @@ public interface ILinqToDBForEFTools
3738
/// </summary>
3839
/// <param name="model">EF.Core data model.</param>
3940
/// <param name="dependencies"></param>
41+
/// <param name="mappingSource"></param>
4042
/// <returns>LINQ To DB metadata provider for specified EF.Core model. Can return <c>null</c>.</returns>
41-
IMetadataReader CreateMetadataReader(IModel model, RelationalSqlTranslatingExpressionVisitorDependencies dependencies);
43+
IMetadataReader CreateMetadataReader(IModel model, RelationalSqlTranslatingExpressionVisitorDependencies dependencies, IRelationalTypeMappingSource mappingSource);
4244

4345
/// <summary>
4446
/// Creates mapping schema using provided EF.Core data model and metadata provider.

Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.cs

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public static ILinqToDBForEFTools Implementation
8989
{
9090
_implementation = value ?? throw new ArgumentNullException(nameof(value));
9191
_metadataReaders.Clear();
92-
_defaultMeadataReader = new Lazy<IMetadataReader>(() => Implementation.CreateMetadataReader(null, null));
92+
_defaultMeadataReader = new Lazy<IMetadataReader>(() => Implementation.CreateMetadataReader(null, null, null));
9393
}
9494
}
9595

@@ -121,12 +121,12 @@ static LinqToDBForEFTools()
121121
/// <param name="dependencies"></param>
122122
/// <returns>LINQ To DB metadata provider.</returns>
123123
public static IMetadataReader GetMetadataReader([JetBrains.Annotations.CanBeNull] IModel model,
124-
RelationalSqlTranslatingExpressionVisitorDependencies dependencies)
124+
RelationalSqlTranslatingExpressionVisitorDependencies dependencies, IRelationalTypeMappingSource mappingSource)
125125
{
126126
if (model == null)
127127
return _defaultMeadataReader.Value;
128128

129-
return _metadataReaders.GetOrAdd(model, m => Implementation.CreateMetadataReader(model, dependencies));
129+
return _metadataReaders.GetOrAdd(model, m => Implementation.CreateMetadataReader(model, dependencies, mappingSource));
130130
}
131131

132132
/// <summary>
@@ -211,11 +211,13 @@ public static IDataProvider GetDataProvider(EFProviderInfo info, EFConnectionInf
211211
/// </summary>
212212
/// <param name="model">EF.Core data model.</param>
213213
/// <param name="dependencies"></param>
214+
/// <param name="mappingSource"></param>
214215
/// <returns>Mapping schema for provided EF.Core model.</returns>
215216
public static MappingSchema GetMappingSchema(IModel model,
216-
RelationalSqlTranslatingExpressionVisitorDependencies dependencies)
217+
RelationalSqlTranslatingExpressionVisitorDependencies dependencies,
218+
IRelationalTypeMappingSource mappingSource)
217219
{
218-
return Implementation.GetMappingSchema(model, GetMetadataReader(model, dependencies));
220+
return Implementation.GetMappingSchema(model, GetMetadataReader(model, dependencies, mappingSource));
219221
}
220222

221223
/// <summary>
@@ -275,7 +277,8 @@ public static DataConnection CreateLinqToDbConnection(this DbContext context,
275277
dc.OnTraceConnection = t => Implementation.LogConnectionTrace(t, logger);
276278

277279
var dependencies = context.GetService<RelationalSqlTranslatingExpressionVisitorDependencies>();
278-
var mappingSchema = GetMappingSchema(context.Model, dependencies);
280+
var mappingSource = context.GetService<IRelationalTypeMappingSource>();
281+
var mappingSchema = GetMappingSchema(context.Model, dependencies, mappingSource);
279282
if (mappingSchema != null)
280283
dc.AddMappingSchema(mappingSchema);
281284

@@ -301,7 +304,8 @@ public static IDataContext CreateLinqToDbContext(this DbContext context,
301304
var connectionInfo = GetConnectionInfo(info);
302305
var provider = GetDataProvider(info, connectionInfo);
303306
var dependencies = context.GetService<RelationalSqlTranslatingExpressionVisitorDependencies>();
304-
var mappingSchema = GetMappingSchema(context.Model, dependencies);
307+
var mappingSource = context.GetService<IRelationalTypeMappingSource>();
308+
var mappingSchema = GetMappingSchema(context.Model, dependencies, mappingSource);
305309
var logger = CreateLogger(info.Options);
306310

307311
if (transaction != null)
@@ -323,7 +327,7 @@ public static IDataContext CreateLinqToDbContext(this DbContext context,
323327

324328
if (mappingSchema != null)
325329
dataContext.MappingSchema = mappingSchema;
326-
330+
327331
if (logger != null)
328332
dataContext.OnTraceConnection = t => Implementation.LogConnectionTrace(t, logger);
329333

@@ -360,7 +364,8 @@ public static DataConnection CreateLinq2DbConnectionDetached([JetBrains.Annotati
360364
dc.OnTraceConnection = t => Implementation.LogConnectionTrace(t, logger);
361365

362366
var dependencies = context.GetService<RelationalSqlTranslatingExpressionVisitorDependencies>();
363-
var mappingSchema = GetMappingSchema(context.Model, dependencies);
367+
var mappingSource = context.GetService<IRelationalTypeMappingSource>();
368+
var mappingSchema = GetMappingSchema(context.Model, dependencies, mappingSource);
364369
if (mappingSchema != null)
365370
dc.AddMappingSchema(mappingSchema);
366371

@@ -431,7 +436,7 @@ public static DataConnection CreateLinqToDbConnection(this DbContextOptions opti
431436

432437
if (model != null)
433438
{
434-
var mappingSchema = GetMappingSchema(model, null);
439+
var mappingSchema = GetMappingSchema(model, null, null);
435440
if (mappingSchema != null)
436441
dc.AddMappingSchema(mappingSchema);
437442
}
@@ -452,11 +457,7 @@ public static IQueryable<T> ToLinqToDB<T>(this IQueryable<T> query, IDataContext
452457
if (context == null)
453458
throw new LinqToDBForEFToolsException("Can not evaluate current context from query");
454459

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

462463
/// <summary>
@@ -478,11 +479,7 @@ public static IQueryable<T> ToLinqToDB<T>(this IQueryable<T> query)
478479

479480
var dc = CreateLinqToDbContext(context);
480481

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

488485
/// <summary>

Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Microsoft.EntityFrameworkCore;
1313
using Microsoft.EntityFrameworkCore.Infrastructure;
1414
using Microsoft.EntityFrameworkCore.Metadata;
15+
using Microsoft.EntityFrameworkCore.Storage;
1516
using Microsoft.EntityFrameworkCore.Query;
1617
using Microsoft.EntityFrameworkCore.Query.Internal;
1718
using Microsoft.Extensions.Logging;
@@ -332,11 +333,13 @@ protected virtual IDataProvider CreatePostgreSqlProvider(PostgreSQLVersion versi
332333
/// </summary>
333334
/// <param name="model">EF.Core data model.</param>
334335
/// <param name="dependencies"></param>
336+
/// <param name="mappingSource"></param>
335337
/// <returns>LINQ To DB metadata provider for specified EF.Core model.</returns>
336338
public virtual IMetadataReader CreateMetadataReader(IModel model,
337-
RelationalSqlTranslatingExpressionVisitorDependencies dependencies)
339+
RelationalSqlTranslatingExpressionVisitorDependencies dependencies,
340+
IRelationalTypeMappingSource mappingSource)
338341
{
339-
return new EFCoreMetadataReader(model, dependencies);
342+
return new EFCoreMetadataReader(model, dependencies, mappingSource);
340343
}
341344

342345
/// <summary>

Tests/LinqToDB.EntityFrameworkCore.Tests/ConflictTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using LinqToDB.Data;
33
using LinqToDB.EntityFrameworkCore;
44
using LinqToDB.EntityFrameworkCore.Tests;
5+
using LinqToDB.EntityFrameworkCore.Tests.Models.AdventuresWorks;
56
using Microsoft.EntityFrameworkCore;
67
using Microsoft.EntityFrameworkCore.SqlAzure.Model;
78
using NUnit.Framework;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.0.1" />
2121
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
2222
<PackageReference Include="NUnit" Version="3.12.0" />
23-
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" />
23+
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.0.0-rc1.final" />
2424
</ItemGroup>
2525

2626
<ItemGroup>

Tests/LinqToDB.EntityFrameworkCore.Tests/Logging/TestLoggerFactory.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.

Tests/LinqToDB.EntityFrameworkCore.Tests/Models/AdventuresWorks/AdventureWorksContext.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using LinqToDB.EntityFrameworkCore.Tests.Model;
5-
using NUnit.Framework.Internal;
5+
using Microsoft.EntityFrameworkCore;
6+
using Microsoft.EntityFrameworkCore.SqlAzure.Model;
67

7-
namespace Microsoft.EntityFrameworkCore.SqlAzure.Model
8+
namespace LinqToDB.EntityFrameworkCore.Tests.Models.AdventuresWorks
89
{
910
public class AdventureWorksContext : DbContext
1011
{

0 commit comments

Comments
 (0)