From 05fc67a2aa254d95618f2057978093e827fb4ed7 Mon Sep 17 00:00:00 2001 From: Artiom Chilaru Date: Thu, 21 Nov 2024 21:53:26 +0000 Subject: [PATCH] Additional improvements and code cleanup --- Directory.Build.props | 4 ++-- FlexLabs.Upsert.sln | 1 + .../Internal/ConstantValue.cs | 5 ++--- .../Internal/PropertyValue.cs | 5 ++--- .../InvalidMatchColumnsException.cs | 1 - .../Runners/InMemoryUpsertCommandRunner.cs | 5 ++--- .../Runners/MySqlUpsertCommandRunner.cs | 3 ++- .../Runners/PostgreSqlUpsertCommandRunner.cs | 5 +++-- .../Runners/RelationalUpsertCommandRunner.cs | 13 +++++------ .../Runners/RunnerQueryOptions.cs | 5 +---- .../Runners/SqlServerUpsertCommandRunner.cs | 5 +++-- .../Runners/UpsertCommandRunnerBase.cs | 22 ++++++++----------- .../UnsupportedExpressionException.cs | 3 +-- .../UpsertCommandBuilder.cs | 7 ++---- ...ameworkCore.Upsert.IntegrationTests.csproj | 16 +++++++------- ...bs.EntityFrameworkCore.Upsert.Tests.csproj | 10 ++++----- .../RelationalCommandRunnerTestsBase.cs | 8 +++---- 17 files changed, 51 insertions(+), 67 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index eb3e898..2feb070 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,9 +1,9 @@ - + - + \ No newline at end of file diff --git a/FlexLabs.Upsert.sln b/FlexLabs.Upsert.sln index 6d1a3e7..f96b47a 100644 --- a/FlexLabs.Upsert.sln +++ b/FlexLabs.Upsert.sln @@ -6,6 +6,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".solution", ".solution", "{ ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig build.release.signed.bat = build.release.signed.bat + Directory.Build.props = Directory.Build.props README.md = README.md EndProjectSection EndProject diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/Internal/ConstantValue.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/Internal/ConstantValue.cs index 92ba42b..3bd42d0 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/Internal/ConstantValue.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/Internal/ConstantValue.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Reflection; using Microsoft.EntityFrameworkCore.Metadata; @@ -52,7 +51,7 @@ public IEnumerable GetConstantValues() /// public IEnumerable GetPropertyValues() { - return Array.Empty(); + return []; } } } diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/Internal/PropertyValue.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/Internal/PropertyValue.cs index b65fcad..a5acd44 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/Internal/PropertyValue.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/Internal/PropertyValue.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Metadata; namespace FlexLabs.EntityFrameworkCore.Upsert.Internal @@ -40,7 +39,7 @@ public PropertyValue(string propertyName, bool isLeftParameter, IProperty proper /// public IEnumerable GetConstantValues() { - return Array.Empty(); + return []; } /// diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/InvalidMatchColumnsException.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/InvalidMatchColumnsException.cs index 720c199..3227960 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/InvalidMatchColumnsException.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/InvalidMatchColumnsException.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; namespace FlexLabs.EntityFrameworkCore.Upsert { diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/InMemoryUpsertCommandRunner.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/InMemoryUpsertCommandRunner.cs index 99a24cb..f72aeae 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/InMemoryUpsertCommandRunner.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/InMemoryUpsertCommandRunner.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -107,7 +106,7 @@ public EntityMatch(TEntity? dbEntity, TEntity newEntity) public TEntity NewEntity; } - private static ICollection> FindMatches(IEntityType entityType, IEnumerable entities, DbContext dbContext, + private static EntityMatch[] FindMatches(IEntityType entityType, IEnumerable entities, DbContext dbContext, Expression>? matchExpression) where TEntity : class { if (matchExpression != null) @@ -119,7 +118,7 @@ private static ICollection> FindMatches(IEntityTyp // If we're resorting to matching on PKs, we'll have to load them manually var primaryKeyProperties = entityType.FindPrimaryKey()?.Properties; if (primaryKeyProperties == null) - return Array.Empty>(); + return []; object?[] getPKs(TEntity entity) { diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/MySqlUpsertCommandRunner.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/MySqlUpsertCommandRunner.cs index e15b532..89e0d4b 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/MySqlUpsertCommandRunner.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/MySqlUpsertCommandRunner.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using FlexLabs.EntityFrameworkCore.Upsert.Internal; @@ -33,7 +34,7 @@ public override string GenerateCommand(string tableName, ICollection EscapeName(e.ColumnName)))); result.Append(") VALUES ("); result.Append(string.Join("), (", entities.Select(ec => string.Join(", ", ec.Select(e => e.DefaultSql ?? Parameter(e.Value.ArgumentIndex)))))); diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/PostgreSqlUpsertCommandRunner.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/PostgreSqlUpsertCommandRunner.cs index a432b47..712c4b2 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/PostgreSqlUpsertCommandRunner.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/PostgreSqlUpsertCommandRunner.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using FlexLabs.EntityFrameworkCore.Upsert.Internal; @@ -27,7 +28,7 @@ public override string GenerateCommand(string tableName, ICollection EscapeName(e.ColumnName)))); result.Append(") VALUES ("); result.Append(string.Join("), (", entities.Select(ec => string.Join(", ", ec.Select(e => e.DefaultSql ?? Parameter(e.Value.ArgumentIndex)))))); @@ -39,7 +40,7 @@ public override string GenerateCommand(string tableName, ICollection $"{EscapeName(e.ColumnName)} = {ExpandValue(e.Value)}"))); if (updateCondition != null) - result.Append($" WHERE {ExpandExpression(updateCondition)}"); + result.Append(CultureInfo.InvariantCulture, $" WHERE {ExpandExpression(updateCondition)}"); } else { diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/RelationalUpsertCommandRunner.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/RelationalUpsertCommandRunner.cs index a1213c4..b7f1eec 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/RelationalUpsertCommandRunner.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/RelationalUpsertCommandRunner.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Data; using System.Data.Common; -using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Threading; @@ -116,13 +115,11 @@ protected virtual string GetTableName(IEntityType entityType) if (updater.Body is not MemberInitExpression entityUpdater) throw new ArgumentException(Resources.FormatUpdaterMustBeAnInitialiserOfTheTEntityType(nameof(updater)), nameof(updater)); - updateExpressions = new List<(IProperty Property, IKnownValue Value)>(); + updateExpressions = []; foreach (MemberAssignment binding in entityUpdater.Bindings) { - var property = entityType.FindProperty(binding.Member.Name); - if (property == null) - throw new InvalidOperationException("Unknown property " + binding.Member.Name); - + var property = entityType.FindProperty(binding.Member.Name) + ?? throw new InvalidOperationException("Unknown property " + binding.Member.Name); var value = binding.Expression.GetValue(updater, entityType.FindProperty, queryOptions.UseExpressionCompiler); if (value is not IKnownValue knownVal) knownVal = new ConstantValue(value, property); @@ -132,7 +129,7 @@ protected virtual string GetTableName(IEntityType entityType) } else if (!queryOptions.NoUpdate) { - updateExpressions = new List<(IProperty Property, IKnownValue Value)>(); + updateExpressions = []; foreach (var property in properties) { if (joinColumnNames.Any(c => c.ColumnName == property.GetColumnName())) @@ -399,7 +396,7 @@ public override async Task RunAsync(DbContext dbContext, IEntityTy return result; } - private object PrepareDbCommandArgument(DbCommand dbCommand, IRelationalTypeMappingSource relationalTypeMappingSource, ConstantValue constantValue) + private DbParameter PrepareDbCommandArgument(DbCommand dbCommand, IRelationalTypeMappingSource relationalTypeMappingSource, ConstantValue constantValue) { RelationalTypeMapping? relationalTypeMapping = null; diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/RunnerQueryOptions.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/RunnerQueryOptions.cs index b0e66eb..50fcdb3 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/RunnerQueryOptions.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/RunnerQueryOptions.cs @@ -1,11 +1,8 @@ -using System.Diagnostics.CodeAnalysis; - -namespace FlexLabs.EntityFrameworkCore.Upsert.Runners +namespace FlexLabs.EntityFrameworkCore.Upsert.Runners { /// /// Options to configure the query behaviour /// - [SuppressMessage("Performance", "CA1815:Override equals and operator equals on value types", Justification = "There would be no need to compare instances of these options")] public struct RunnerQueryOptions { /// diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/SqlServerUpsertCommandRunner.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/SqlServerUpsertCommandRunner.cs index 15c99c8..4acd85a 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/SqlServerUpsertCommandRunner.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/SqlServerUpsertCommandRunner.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using FlexLabs.EntityFrameworkCore.Upsert.Internal; @@ -27,7 +28,7 @@ public override string GenerateCommand(string tableName, ICollection string.Join(", ", ec.Select(e => e.DefaultSql ?? Parameter(e.Value.ArgumentIndex)))))); result.Append($") ) AS [S] ("); result.Append(string.Join(", ", entities.First().Select(e => EscapeName(e.ColumnName)))); @@ -44,7 +45,7 @@ public override string GenerateCommand(string tableName, ICollection $"{EscapeName(e.ColumnName)} = {ExpandValue(e.Value)}"))); } diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/UpsertCommandRunnerBase.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/UpsertCommandRunnerBase.cs index 69ef403..c0c8c45 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/UpsertCommandRunnerBase.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/Runners/UpsertCommandRunnerBase.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -50,14 +49,13 @@ protected static ICollection ProcessMatchExpression(IEntityT } else if (matchExpression.Body is NewExpression newExpression) { - joinColumns = new List(); + joinColumns = []; foreach (MemberExpression arg in newExpression.Arguments) { if (arg == null || arg.Member is not PropertyInfo || !typeof(TEntity).Equals(arg.Expression?.Type)) throw new InvalidOperationException(Resources.MatchColumnsHaveToBePropertiesOfTheTEntityClass); - var property = entityType.FindProperty(arg.Member.Name); - if (property == null) - throw new InvalidOperationException(Resources.FormatUnknownProperty(arg.Member.Name)); + var property = entityType.FindProperty(arg.Member.Name) + ?? throw new InvalidOperationException(Resources.FormatUnknownProperty(arg.Member.Name)); joinColumns.Add(property); } } @@ -65,19 +63,17 @@ protected static ICollection ProcessMatchExpression(IEntityT { if (unaryExpression.Operand is not MemberExpression memberExp || memberExp.Member is not PropertyInfo || !typeof(TEntity).Equals(memberExp.Expression?.Type)) throw new InvalidOperationException(Resources.MatchColumnsHaveToBePropertiesOfTheTEntityClass); - var property = entityType.FindProperty(memberExp.Member.Name); - if (property == null) - throw new InvalidOperationException(Resources.FormatUnknownProperty(memberExp.Member.Name)); - joinColumns = new List { property }; + var property = entityType.FindProperty(memberExp.Member.Name) + ?? throw new InvalidOperationException(Resources.FormatUnknownProperty(memberExp.Member.Name)); + joinColumns = [property]; } else if (matchExpression.Body is MemberExpression memberExpression) { if (!typeof(TEntity).Equals(memberExpression.Expression?.Type) || memberExpression.Member is not PropertyInfo) throw new InvalidOperationException(Resources.MatchColumnsHaveToBePropertiesOfTheTEntityClass); - var property = entityType.FindProperty(memberExpression.Member.Name); - if (property == null) - throw new InvalidOperationException(Resources.FormatUnknownProperty(memberExpression.Member.Name)); - joinColumns = new List { property }; + var property = entityType.FindProperty(memberExpression.Member.Name) + ?? throw new InvalidOperationException(Resources.FormatUnknownProperty(memberExpression.Member.Name)); + joinColumns = [property]; } else { diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/UnsupportedExpressionException.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/UnsupportedExpressionException.cs index a7b296b..80bee54 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/UnsupportedExpressionException.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/UnsupportedExpressionException.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; namespace FlexLabs.EntityFrameworkCore.Upsert { @@ -23,7 +22,7 @@ internal UnsupportedExpressionException(System.Linq.Expressions.Expression expre } internal static UnsupportedExpressionException MySQLConditionalUpdate() - => new UnsupportedExpressionException(Resources.UsingConditionalUpdatesIsNotSupportedInMySQLDueToDatabaseSyntaxLimitations + " " + + => new(Resources.UsingConditionalUpdatesIsNotSupportedInMySQLDueToDatabaseSyntaxLimitations + " " + Resources.FormatSeeLinkForMoreDetails(HelpLinks.MySQLConditionalUpdate), HelpLinks.MySQLConditionalUpdate); } diff --git a/src/FlexLabs.EntityFrameworkCore.Upsert/UpsertCommandBuilder.cs b/src/FlexLabs.EntityFrameworkCore.Upsert/UpsertCommandBuilder.cs index b5d0b35..8fde16a 100644 --- a/src/FlexLabs.EntityFrameworkCore.Upsert/UpsertCommandBuilder.cs +++ b/src/FlexLabs.EntityFrameworkCore.Upsert/UpsertCommandBuilder.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Threading; @@ -171,10 +170,8 @@ private IUpsertCommandRunner GetCommandRunner() var dbProvider = _dbContext.GetService(); var commandRunner = _dbContext.GetInfrastructure().GetServices() .Concat(DefaultRunners.GetRunners()) - .FirstOrDefault(r => r.Supports(dbProvider.Name)); - if (commandRunner == null) - throw new NotSupportedException(Resources.DatabaseProviderNotSupportedYet); - + .FirstOrDefault(r => r.Supports(dbProvider.Name)) + ?? throw new NotSupportedException(Resources.DatabaseProviderNotSupportedYet); return commandRunner; } diff --git a/test/FlexLabs.EntityFrameworkCore.Upsert.IntegrationTests/FlexLabs.EntityFrameworkCore.Upsert.IntegrationTests.csproj b/test/FlexLabs.EntityFrameworkCore.Upsert.IntegrationTests/FlexLabs.EntityFrameworkCore.Upsert.IntegrationTests.csproj index 4f1d494..9088ecd 100644 --- a/test/FlexLabs.EntityFrameworkCore.Upsert.IntegrationTests/FlexLabs.EntityFrameworkCore.Upsert.IntegrationTests.csproj +++ b/test/FlexLabs.EntityFrameworkCore.Upsert.IntegrationTests/FlexLabs.EntityFrameworkCore.Upsert.IntegrationTests.csproj @@ -12,24 +12,24 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/FlexLabs.EntityFrameworkCore.Upsert.Tests/FlexLabs.EntityFrameworkCore.Upsert.Tests.csproj b/test/FlexLabs.EntityFrameworkCore.Upsert.Tests/FlexLabs.EntityFrameworkCore.Upsert.Tests.csproj index ae75834..0737e8d 100644 --- a/test/FlexLabs.EntityFrameworkCore.Upsert.Tests/FlexLabs.EntityFrameworkCore.Upsert.Tests.csproj +++ b/test/FlexLabs.EntityFrameworkCore.Upsert.Tests/FlexLabs.EntityFrameworkCore.Upsert.Tests.csproj @@ -8,16 +8,16 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/FlexLabs.EntityFrameworkCore.Upsert.Tests/Runners/RelationalCommandRunnerTestsBase.cs b/test/FlexLabs.EntityFrameworkCore.Upsert.Tests/Runners/RelationalCommandRunnerTestsBase.cs index 736cd05..4f20dec 100644 --- a/test/FlexLabs.EntityFrameworkCore.Upsert.Tests/Runners/RelationalCommandRunnerTestsBase.cs +++ b/test/FlexLabs.EntityFrameworkCore.Upsert.Tests/Runners/RelationalCommandRunnerTestsBase.cs @@ -1,11 +1,10 @@ -using System; +using System; using System.Collections.Generic; using System.Data.Common; using FlexLabs.EntityFrameworkCore.Upsert.Runners; using FlexLabs.EntityFrameworkCore.Upsert.Tests.Runners.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Storage; @@ -75,9 +74,8 @@ protected static EntityType AddEntity(Model model) { entityType.AddProperty(property.Name, ConfigurationSource.Explicit); } - var idProperty = entityType.FindProperty("ID"); - if (idProperty == null) - throw new InvalidOperationException("ID property missing on entity " + typeof(TEntity).Name); + var idProperty = entityType.FindProperty("ID") + ?? throw new InvalidOperationException("ID property missing on entity " + typeof(TEntity).Name); entityType.AddKey(idProperty, ConfigurationSource.Convention); return entityType; }