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

Commit bede9a6

Browse files
authored
.net 8 migration (#358)
* .net 8 migration * ci: install net8 sdk * fix ci * fix ci * update linq2db, ignore mysql exceptions from call translator * sqlite identity fix * mysql fix * update linq2db
1 parent ea431c3 commit bede9a6

File tree

46 files changed

+544
-487
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+544
-487
lines changed

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ indent_style = tab
55
indent_size = 4
66
insert_final_newline = true
77
end_of_line = crlf
8+
spelling_exclusion_path = spellcheck.txt
89

910
# Code files
1011
[*.{cs,csx,vb,vbx}]
@@ -160,15 +161,20 @@ dotnet_diagnostic.CA3076.severity = none # CA3076: Insecure XSLT Script Executio
160161
#########################################################################################################
161162
dotnet_diagnostic.CA1000.severity = none # CA1000: Do not declare static members on generic types
162163
dotnet_diagnostic.CA1001.severity = none # CA1001: Types that own disposable fields should be disposable
164+
dotnet_diagnostic.CA1002.severity = none # CA1002: Do not expose generic lists
163165
dotnet_diagnostic.CA1010.severity = none # CA1010: Collections should implement generic interface
166+
dotnet_diagnostic.CA1033.severity = none # CA1033: Interface methods should be callable by child types
164167
dotnet_diagnostic.CA1050.severity = none # CA1050: Declare types in namespaces
165168
dotnet_diagnostic.CA1036.severity = none # CA1036: Override methods on comparable types
166169
dotnet_diagnostic.CA1051.severity = none # CA1051: Do not declare visible instance fields
170+
dotnet_diagnostic.CA1056.severity = none # CA1056: URI properties should not be strings
171+
dotnet_diagnostic.CA1062.severity = none # CA1062: Validate arguments of public methods
167172
dotnet_diagnostic.CA1067.severity = none # CA1067: Override Equals when implementing IEquatable
168173
dotnet_diagnostic.CA1068.severity = none # CA1068: CancellationToken parameters must come last
169174
dotnet_diagnostic.CA1069.severity = none # CA1069: Enums should not have duplicate values
170175
dotnet_diagnostic.CA1304.severity = none # CA1304: Specify CultureInfo
171176
dotnet_diagnostic.CA1305.severity = none # CA1305: Specify IFormatProvider
177+
dotnet_diagnostic.CA1307.severity = none # CA1307: Specify StringComparison for clarity
172178
dotnet_diagnostic.CA1309.severity = none # CA1309: Use ordinal StringComparison
173179
dotnet_diagnostic.CA1310.severity = none # CA1310: Specify StringComparison for correctness
174180
dotnet_diagnostic.CA1707.severity = none # CA1707: Identifiers should not contain underscores
@@ -178,8 +184,12 @@ dotnet_diagnostic.CA1715.severity = none # CA1715: Identifiers should have corre
178184
dotnet_diagnostic.CA1716.severity = none # CA1716: Identifiers should not match keywords
179185
dotnet_diagnostic.CA1720.severity = none # CA1720: Identifiers should not contain type names
180186
dotnet_diagnostic.CA1806.severity = none # CA1806: Do not ignore method results
187+
dotnet_diagnostic.CA1819.severity = none # CA1819: Properties should not return arrays
181188
dotnet_diagnostic.CA1822.severity = none # CA1822: Mark members as static
189+
dotnet_diagnostic.CA1859.severity = none # CA1859: Use concrete types when possible for improved performance
182190
dotnet_diagnostic.CA2211.severity = none # CA2211: Non-constant fields should not be visible
191+
dotnet_diagnostic.CA2225.severity = none # CA2225: Operator overloads have named alternates
192+
dotnet_diagnostic.CA2227.severity = none # CA2227: Remove property setter
183193

184194
###################################################################################
185195
# VS analyzers #
@@ -250,6 +260,8 @@ dotnet_diagnostic.IDE0080.severity = none # IDE0080: Remove unnecessary suppress
250260
dotnet_diagnostic.IDE0081.severity = none # IDE0081: Remove ByVal
251261
dotnet_diagnostic.IDE0083.severity = none # IDE0083: Use pattern matching (not operator)
252262
dotnet_diagnostic.IDE0130.severity = none # IDE0130: Namespace does not match folder structure
263+
dotnet_diagnostic.IDE0290.severity = none # IDE0290: Use primary constructor
264+
dotnet_diagnostic.IDE0305.severity = none # IDE0305: Use collection expression (from ToArray)
253265
dotnet_diagnostic.IDE1006.severity = none # IDE1006: Naming rule violation
254266

255267
dotnet_diagnostic.CS1998.severity = error # CS1998: Async method lacks 'await' operators and will run synchronously

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
22
<PropertyGroup>
3-
<Version>7.6.0</Version>
3+
<Version>8.0.0</Version>
44

55
<Authors>Svyatoslav Danyliv, Igor Tkachev, Dmitry Lukashenko, Ilya Chudin</Authors>
66
<Product>Linq to DB</Product>
@@ -38,7 +38,7 @@
3838

3939
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
4040

41-
<TargetFrameworks>net6.0</TargetFrameworks>
41+
<TargetFrameworks>net8.0</TargetFrameworks>
4242
</PropertyGroup>
4343

4444
<PropertyGroup>

Directory.Packages.props

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,21 @@
55
<PackageVersion Include="NUnit" Version="3.13.3" />
66
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
77

8-
<PackageVersion Include="linq2db" Version="5.3.0" />
9-
<PackageVersion Include="linq2db.Tools" Version="5.3.0" />
8+
<PackageVersion Include="linq2db" Version="5.3.1" />
9+
<PackageVersion Include="linq2db.Tools" Version="5.3.1" />
1010

1111
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
1212

13-
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.0" />
14-
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0" />
13+
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.0-rc.2.23480.1" />
14+
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0-rc.2.23480.1" />
1515

16-
<PackageVersion Include="Microsoft.Extensions.Logging" Version="7.0.0" />
17-
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
16+
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.0-rc.2.23479.6" />
1817

19-
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
20-
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="7.0.11" />
21-
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.12" />
22-
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.12" />
18+
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0-beta.2.ci.20231014172607+sha.60ea450" />
19+
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="8.0.0-rc.2" />
20+
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-rc.2.23480.1" />
21+
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-rc.2.23480.1" />
2322

2423
<PackageVersion Include="EntityFrameworkCore.FSharp" Version="6.0.7" />
25-
<PackageVersion Include="FSharp.Core" Version="7.0.400" />
2624
</ItemGroup>
2725
</Project>

NuGet.config

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,15 @@
33
<packageSources>
44
<clear />
55
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
6+
<add key="pomelo-nightly" value="https://pkgs.dev.azure.com/pomelo-efcore/Pomelo.EntityFrameworkCore.MySql/_packaging/pomelo-efcore-public/nuget/v3/index.json" />
7+
<add key="linq2db" value="https://pkgs.dev.azure.com/linq2db/linq2db/_packaging/linq2db/nuget/v3/index.json" />
68
</packageSources>
9+
<packageSourceMapping>
10+
<packageSource key="pomelo-nightly">
11+
<package pattern="Pomelo.EntityFrameworkCore.MySql" />
12+
</packageSource>
13+
<packageSource key="nuget.org">
14+
<package pattern="*" />
15+
</packageSource>
16+
</packageSourceMapping>
717
</configuration>

NuGet/linq2db.EntityFrameworkCore.nuspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
<projectUrl>https://github.com/linq2db/linq2db.EntityFrameworkCore</projectUrl>
1515
<license type="file">MIT-LICENSE.txt</license>
1616
<dependencies>
17-
<group targetFramework="net6.0">
18-
<dependency id="Microsoft.EntityFrameworkCore.Relational" version="7.0.0" />
19-
<dependency id="linq2db" version="5.3.0" />
17+
<group targetFramework="net8.0">
18+
<dependency id="Microsoft.EntityFrameworkCore.Relational" version="8.0.0-rc.2.23480.1" />
19+
<dependency id="linq2db" version="5.3.1" />
2020
</group>
2121
</dependencies>
2222
</metadata>

Source/LinqToDB.EntityFrameworkCore/EFCoreMetadataReader.cs

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Linq.Expressions;
77
using System.Reflection;
88
using System.Runtime.CompilerServices;
9+
using LinqToDB.Common.Internal;
910
using Microsoft.EntityFrameworkCore;
1011
using Microsoft.EntityFrameworkCore.Diagnostics;
1112
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -39,17 +40,19 @@ internal sealed class EFCoreMetadataReader : IMetadataReader
3940
private readonly IRelationalAnnotationProvider? _annotationProvider;
4041
private readonly ConcurrentDictionary<MemberInfo, EFCoreExpressionAttribute?> _calculatedExtensions = new();
4142
private readonly IDiagnosticsLogger<DbLoggerCategory.Query>? _logger;
43+
private readonly DatabaseDependencies? _databaseDependencies;
4244

4345
public EFCoreMetadataReader(IModel? model, IInfrastructure<IServiceProvider>? accessor)
4446
{
4547
_model = model;
4648

4749
if (accessor != null)
4850
{
49-
_dependencies = accessor.GetService<RelationalSqlTranslatingExpressionVisitorDependencies>();
50-
_mappingSource = accessor.GetService<IRelationalTypeMappingSource>();
51-
_annotationProvider = accessor.GetService<IRelationalAnnotationProvider>();
52-
_logger = accessor.GetService<IDiagnosticsLogger<DbLoggerCategory.Query>>();
51+
_dependencies = accessor.GetService<RelationalSqlTranslatingExpressionVisitorDependencies>();
52+
_mappingSource = accessor.GetService<IRelationalTypeMappingSource>();
53+
_annotationProvider = accessor.GetService<IRelationalAnnotationProvider>();
54+
_logger = accessor.GetService<IDiagnosticsLogger<DbLoggerCategory.Query>>();
55+
_databaseDependencies = accessor.GetService<DatabaseDependencies>();
5356
}
5457

5558
_objectId = $".{_model?.GetHashCode() ?? 0}.{_dependencies?.GetHashCode() ?? 0}.{_mappingSource?.GetHashCode() ?? 0}.{_annotationProvider?.GetHashCode() ?? 0}.{_logger?.GetHashCode() ?? 0}.";
@@ -124,10 +127,10 @@ public MappingAttribute[] GetAttributes(Type type)
124127
// TableAttribute
125128
var tableAttribute = type.GetAttribute<System.ComponentModel.DataAnnotations.Schema.TableAttribute>();
126129
if (tableAttribute != null)
127-
(result ??= new()).Add(new TableAttribute(tableAttribute.Name) { Schema = tableAttribute.Schema });
130+
(result = new()).Add(new TableAttribute(tableAttribute.Name) { Schema = tableAttribute.Schema });
128131
}
129132

130-
return result == null ? Array.Empty<MappingAttribute>() : result.ToArray();
133+
return result == null ? [] : result.ToArray();
131134
}
132135

133136
static IEntityType GetBaseTypeRecursive(IEntityType entityType)
@@ -137,7 +140,7 @@ static IEntityType GetBaseTypeRecursive(IEntityType entityType)
137140
return GetBaseTypeRecursive(entityType.BaseType);
138141
}
139142

140-
static IEnumerable<InheritanceMappingAttribute> GetMappingAttributesRecursive(IEntityType entityType)
143+
static List<InheritanceMappingAttribute> GetMappingAttributesRecursive(IEntityType entityType)
141144
{
142145
var mappings = new List<InheritanceMappingAttribute>();
143146
return ProcessEntityType(entityType);
@@ -221,7 +224,7 @@ static DataType DbTypeToDataType(DbType dbType)
221224
public MappingAttribute[] GetAttributes(Type type, MemberInfo memberInfo)
222225
{
223226
if (typeof(Expression).IsSameOrParentOf(type))
224-
return Array.Empty<MappingAttribute>();
227+
return [];
225228

226229
List<MappingAttribute>? result = null;
227230
var hasColumn = false;
@@ -258,14 +261,30 @@ public MappingAttribute[] GetAttributes(Type type, MemberInfo memberInfo)
258261

259262
var storeObjectId = GetStoreObjectIdentifier(et);
260263

264+
var isIdentity = false;
261265
var annotations = prop.GetAnnotations();
262266
if (_annotationProvider != null && storeObjectId != null)
263267
{
264268
if (prop.FindColumn(storeObjectId.Value) is IColumn column)
265269
annotations = annotations.Concat(_annotationProvider.For(column, false));
270+
271+
if (_annotationProvider.GetType().Name == "SqliteAnnotationProvider")
272+
{
273+
// copy-paste logic, not available anymore in v8
274+
// https://github.com/dotnet/efcore/blob/release/8.0/src/EFCore.Sqlite.Core/Metadata/Internal/SqliteAnnotationProvider.cs#L70-L75
275+
var primaryKey = prop.DeclaringType.ContainingEntityType.FindPrimaryKey();
276+
if (primaryKey is { Properties.Count: 1 }
277+
&& primaryKey.Properties[0] == prop
278+
&& prop.ValueGenerated == ValueGenerated.OnAdd
279+
&& prop.ClrType.IsInteger()
280+
&& prop.FindTypeMapping()?.Converter == null)
281+
{
282+
isIdentity = true;
283+
}
284+
}
266285
}
267286

268-
var isIdentity = annotations
287+
isIdentity = isIdentity || annotations
269288
.Any(static a =>
270289
{
271290
if (a.Name.EndsWith(":ValueGenerationStrategy"))
@@ -279,7 +298,7 @@ public MappingAttribute[] GetAttributes(Type type, MemberInfo memberInfo)
279298
{
280299
if (a.Value is string str)
281300
{
282-
return str.ToLowerInvariant().Contains("nextval");
301+
return str.Contains("nextval", StringComparison.InvariantCultureIgnoreCase);
283302
}
284303
}
285304

@@ -301,15 +320,15 @@ public MappingAttribute[] GetAttributes(Type type, MemberInfo memberInfo)
301320
}
302321
}
303322

304-
var behaviour = prop.GetBeforeSaveBehavior();
323+
var behavior = prop.GetBeforeSaveBehavior();
305324
var skipOnInsert = prop.ValueGenerated.HasFlag(ValueGenerated.OnAdd);
306325

307326
if (skipOnInsert)
308327
{
309-
skipOnInsert = isIdentity || behaviour != PropertySaveBehavior.Save;
328+
skipOnInsert = isIdentity || behavior != PropertySaveBehavior.Save;
310329
}
311330

312-
var skipOnUpdate = behaviour != PropertySaveBehavior.Save ||
331+
var skipOnUpdate = behavior != PropertySaveBehavior.Save ||
313332
prop.ValueGenerated.HasFlag(ValueGenerated.OnUpdate);
314333

315334
var ca = new ColumnAttribute()
@@ -432,7 +451,7 @@ public MappingAttribute[] GetAttributes(Type type, MemberInfo memberInfo)
432451
});
433452
}
434453

435-
return result == null ? Array.Empty<MappingAttribute>() : result.ToArray();
454+
return result == null ? [] : result.ToArray();
436455
}
437456

438457
sealed class ValueConverter : IValueConverter
@@ -462,7 +481,7 @@ public SqlTransparentExpression(Expression expression, RelationalTypeMapping? ty
462481

463482
protected override void Print(ExpressionPrinter expressionPrinter)
464483
{
465-
expressionPrinter.Print(Expression);
484+
expressionPrinter.PrintExpression(Expression);
466485
}
467486

468487
private bool Equals(SqlTransparentExpression other)
@@ -493,7 +512,7 @@ public override int GetHashCode()
493512
};
494513
}
495514

496-
private Sql.ExpressionAttribute? GetDbFunctionFromMethodCall(Type type, MethodInfo methodInfo)
515+
private EFCoreExpressionAttribute? GetDbFunctionFromMethodCall(Type type, MethodInfo methodInfo)
497516
{
498517
if (_dependencies == null || _model == null)
499518
return null;
@@ -516,8 +535,20 @@ public override int GetHashCode()
516535
var p = parameterInfos[i];
517536

518537
parametersArray[i] = new SqlTransparentExpression(
519-
Expression.Constant(DefaultValue.GetValue(p.ParameterType), p.ParameterType),
520-
ctx.this_._mappingSource?.FindMapping(p.ParameterType));
538+
Expression.Constant(DefaultValue.GetValue(p.ParameterType), p.ParameterType),
539+
ctx.this_._mappingSource?.FindMapping(p.ParameterType));
540+
}
541+
542+
// https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/issues/1801
543+
if (ctx.this_._dependencies!.MethodCallTranslatorProvider.GetType().Name == "MySqlMethodCallTranslatorProvider")
544+
{
545+
var contextProperty = ctx.this_._dependencies!.MethodCallTranslatorProvider.GetType().GetProperty("QueryCompilationContext")
546+
?? throw new InvalidOperationException("MySqlMethodCallTranslatorProvider.QueryCompilationContext property not found");
547+
548+
if (contextProperty.GetValue(ctx.this_._dependencies!.MethodCallTranslatorProvider) == null)
549+
{
550+
contextProperty.SetValue(ctx.this_._dependencies!.MethodCallTranslatorProvider, ctx.this_._databaseDependencies!.QueryCompilationContextFactory.Create(false));
551+
}
521552
}
522553

523554
var newExpression = ctx.this_._dependencies!.MethodCallTranslatorProvider.Translate(ctx.this_._model!, objExpr, ctx.methodInfo, parametersArray, ctx.this_._logger!);
@@ -536,7 +567,7 @@ public override int GetHashCode()
536567
return found;
537568
}
538569

539-
private Sql.ExpressionAttribute? GetDbFunctionFromProperty(Type type, PropertyInfo propInfo)
570+
private EFCoreExpressionAttribute? GetDbFunctionFromProperty(Type type, PropertyInfo propInfo)
540571
{
541572
if (_dependencies == null || _model == null)
542573
return null;
@@ -629,7 +660,7 @@ string PrepareExpressionText(Expression? expr)
629660
// https://github.com/npgsql/efcore.pg/blob/main/src/EFCore.PG/Query/Expressions/Internal/PostgresBinaryExpression.cs
630661
if (newExpression.GetType().Name == "PostgresBinaryExpression")
631662
{
632-
// Handling NpgSql's PostgresBinaryExpression
663+
// Handling Npgsql PostgresBinaryExpression
633664

634665
var left = (Expression)newExpression.GetType().GetProperty("Left")!.GetValue(newExpression)!;
635666
var right = (Expression)newExpression.GetType().GetProperty("Right")!.GetValue(newExpression)!;
@@ -714,7 +745,7 @@ private static Expression UnwrapConverted(Expression expr)
714745

715746
public MemberInfo[] GetDynamicColumns(Type type)
716747
{
717-
return Array.Empty<MemberInfo>();
748+
return [];
718749
}
719750

720751
string IMetadataReader.GetObjectID() => _objectId;

Source/LinqToDB.EntityFrameworkCore/Internal/EFCoreExpressionAttribute.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace LinqToDB.EntityFrameworkCore.Internal
1010
/// <summary>
1111
/// Maps Linq To DB expression.
1212
/// </summary>
13-
public class EFCoreExpressionAttribute : Sql.ExpressionAttribute
13+
public sealed class EFCoreExpressionAttribute : Sql.ExpressionAttribute
1414
{
1515
/// <summary>
1616
/// Creates instance of expression mapper.
@@ -42,20 +42,20 @@ public EFCoreExpressionAttribute(string expression) : base(expression)
4242
knownExpressions.Add(me.Expression!);
4343
}
4444

45-
var parms = new List<ISqlExpression?>(knownExpressions.Select(_ => (ISqlExpression?) null));
45+
var @params = new List<ISqlExpression?>(knownExpressions.Select(_ => (ISqlExpression?) null));
4646

47-
_ = ResolveExpressionValues((context, parms, knownExpressions, converter), Expression!,
47+
_ = ResolveExpressionValues((context, @params, knownExpressions, converter), Expression!,
4848
static (ctx, v, d) =>
4949
{
5050
var idx = int.Parse(v);
5151

52-
if (ctx.parms[idx] == null)
53-
ctx.parms[idx] = ctx.converter(ctx.context, ctx.knownExpressions[idx], null);
52+
if (ctx.@params[idx] == null)
53+
ctx.@params[idx] = ctx.converter(ctx.context, ctx.knownExpressions[idx], null);
5454

5555
return v;
5656
});
5757

58-
var parameters = parms.Select(p => p ?? new SqlExpression("!!!")).ToArray();
58+
var parameters = @params.Select(p => p ?? new SqlExpression("!!!")).ToArray();
5959
return new SqlExpression(expression.Type, Expression!, Precedence, parameters);
6060
}
6161
}

Source/LinqToDB.EntityFrameworkCore/Internal/LinqToDBForEFQueryProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class LinqToDBForEFQueryProvider<T> : IAsyncQueryProvider, IQueryProvider
3131
/// <param name="expression">Query expression.</param>
3232
public LinqToDBForEFQueryProvider(IDataContext dataContext, Expression expression)
3333
{
34-
if (expression == null) throw new ArgumentNullException(nameof(expression));
34+
ArgumentNullException.ThrowIfNull(expression);
3535
var dataContext1 = dataContext ?? throw new ArgumentNullException(nameof(dataContext));
3636
QueryProvider = (IQueryProviderAsync) Internals.CreateExpressionQueryInstance<T>(dataContext1, expression);
3737
QueryProviderAsQueryable = (IQueryable<T>) QueryProvider;

0 commit comments

Comments
 (0)