From 66f0496f6ca0ab71ea2205fb248bb3d37d6d0b80 Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 14:19:46 -0700 Subject: [PATCH 01/11] Use package repository convention --- .github/conventions.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/conventions.yml b/.github/conventions.yml index 5e5cf36..8e1acfd 100644 --- a/.github/conventions.yml +++ b/.github/conventions.yml @@ -1,10 +1,6 @@ # applied automatically by https://github.com/Faithlife/RepoConventionsApplier (DO NOT REMOVE THIS LINE) conventions: - - path: Faithlife/CodingGuidelines/conventions/faithlife-auto-apply-conventions - - path: Faithlife/CodingGuidelines/conventions/dotnet-common - - path: Faithlife/CodingGuidelines/conventions/faithlife-dotnet-library-build - - path: Faithlife/CodingGuidelines/conventions/faithlife-dotnet-library-workflow - - path: Faithlife/CodingGuidelines/conventions/faithlife-license-mit + - path: Faithlife/CodingGuidelines/conventions/faithlife-dotnet-library pull-request: reviewers: From 0b8bd623ab8aef4b78cec306b7da4948e4490da9 Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 14:20:15 -0700 Subject: [PATCH 02/11] Apply convention nuget-config --- nuget.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuget.config b/nuget.config index 6873eb9..95e879e 100644 --- a/nuget.config +++ b/nuget.config @@ -1,6 +1,6 @@ - + From 9ed17543a95f2b019ecbb937dbfa71580386fff6 Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 14:20:17 -0700 Subject: [PATCH 03/11] Update common .gitignore --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a2ad192..57e0646 100644 --- a/.gitignore +++ b/.gitignore @@ -6,11 +6,15 @@ obj/ release/ *.cache -*.log *.ncrunchproject *.ncrunchsolution *.user launchSettings.json nCrunchTemp* _ReSharper* + +# DO NOT EDIT: gitignore-common convention .DS_Store +Thumbs.db +*.log +# END DO NOT EDIT From 6923c67ef2e9e8f4b72e9fbd26f64fb8aeb8c4de Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 14:20:18 -0700 Subject: [PATCH 04/11] Update .gitignore for .NET --- .gitignore | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 57e0646..dd0859d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,5 @@ .vs/ .idea/ -artifacts/ -bin/ -obj/ -release/ *.cache *.ncrunchproject @@ -18,3 +14,10 @@ _ReSharper* Thumbs.db *.log # END DO NOT EDIT + +# DO NOT EDIT: gitignore-dotnet convention +artifacts/ +bin/ +obj/ +release/ +# END DO NOT EDIT From 372610be95715e24d3c316edf4fa441e451cb008 Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 14:20:20 -0700 Subject: [PATCH 05/11] Update .gitignore for IDEs --- .gitignore | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index dd0859d..e83df5a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,8 @@ -.vs/ -.idea/ -*.cache *.ncrunchproject *.ncrunchsolution -*.user launchSettings.json nCrunchTemp* -_ReSharper* # DO NOT EDIT: gitignore-common convention .DS_Store @@ -21,3 +16,12 @@ bin/ obj/ release/ # END DO NOT EDIT + +# DO NOT EDIT: gitignore-ide convention +.vs/ +.idea/ +*.cache +*.user +*.userprefs +_ReSharper* +# END DO NOT EDIT From 03f4d997c1d23744c74a18c5ce0ae3077ee30288 Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 14:20:23 -0700 Subject: [PATCH 06/11] Update Directory.Packages.props --- Directory.Packages.props | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1bae07e..6335c14 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,4 +15,18 @@ + + + true + true + true + + + + + + + + + \ No newline at end of file From 08b0e72fdcd7a9956fbbffe9c955b394d216d31c Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 14:20:26 -0700 Subject: [PATCH 07/11] Update Directory.Build.props --- Directory.Build.props | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Directory.Build.props b/Directory.Build.props index bbf312a..96bbc3a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -37,5 +37,35 @@ $(VersionPrefix).$(BuildNumber) true + + + 14.0 + enable + enable + true + en-US + embedded + MIT + https://github.com/$(GitHubOrganization)/$(RepositoryName) + https://github.com/$(GitHubOrganization)/$(RepositoryName)/blob/master/ReleaseNotes.md + https://github.com/$(GitHubOrganization)/$(RepositoryName) + Faithlife + Copyright $(Authors) + true + latest-all + true + true + false + false + false + true + true + true + true + true + all + low + + From 4a760e79a919f706d77978dfd533a5533abea5ba Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 14:20:31 -0700 Subject: [PATCH 08/11] Apply convention dotnet-solution-items --- DapperUtility.slnx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DapperUtility.slnx b/DapperUtility.slnx index f6f69a4..416345c 100644 --- a/DapperUtility.slnx +++ b/DapperUtility.slnx @@ -16,9 +16,11 @@ + + From 18d090f4348622231ad969320623468f8208064e Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 15:01:51 -0700 Subject: [PATCH 09/11] Complete .NET library convention migration --- Directory.Build.props | 30 --------------- Directory.Packages.props | 8 ---- .../BulkInsertUtility.cs | 38 +++++++++---------- .../Faithlife.Utility.Dapper.csproj | 1 + .../BulkInsertUtilityTests.cs | 14 +++---- 5 files changed, 27 insertions(+), 64 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 96bbc3a..8828676 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,39 +3,9 @@ 2.0.0 2.0.0 - 12.0 - disable - enable - true $(NoWarn);1591;1998;NU1507;NU5105 - en-US - embedded Faithlife DapperUtility - MIT - https://github.com/$(GitHubOrganization)/$(RepositoryName) - https://github.com/$(GitHubOrganization)/$(RepositoryName)/blob/master/ReleaseNotes.md - https://github.com/$(GitHubOrganization)/$(RepositoryName).git - Faithlife - Copyright $(Authors) - true - true - true - latest-all - true - true - false - false - false - true - true - true - true - - - - $(VersionPrefix).$(BuildNumber) - true diff --git a/Directory.Packages.props b/Directory.Packages.props index 6335c14..db55429 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,7 +1,4 @@ - - true - @@ -10,11 +7,6 @@ - - - - - true diff --git a/src/Faithlife.Utility.Dapper/BulkInsertUtility.cs b/src/Faithlife.Utility.Dapper/BulkInsertUtility.cs index 42c215c..f814185 100644 --- a/src/Faithlife.Utility.Dapper/BulkInsertUtility.cs +++ b/src/Faithlife.Utility.Dapper/BulkInsertUtility.cs @@ -16,15 +16,15 @@ public static class BulkInsertUtility /// /// Efficiently inserts multiple rows, in batches as necessary. /// - public static int BulkInsert(this IDbConnection connection, string sql, IEnumerable insertParams, IDbTransaction transaction = null, int? batchSize = null) + public static int BulkInsert(this IDbConnection connection, string sql, IEnumerable insertParams, IDbTransaction? transaction = null, int? batchSize = null) { - return connection.BulkInsert(sql, (object) null, insertParams, transaction, batchSize); + return connection.BulkInsert(sql, (object?) null, insertParams, transaction, batchSize); } /// /// Efficiently inserts multiple rows, in batches as necessary. /// - public static int BulkInsert(this IDbConnection connection, string sql, TCommon commonParam, IEnumerable insertParams, IDbTransaction transaction = null, int? batchSize = null) + public static int BulkInsert(this IDbConnection connection, string sql, TCommon? commonParam, IEnumerable insertParams, IDbTransaction? transaction = null, int? batchSize = null) { int rowCount = 0; foreach (var commandDefinition in GetBulkInsertCommands(sql, commonParam, insertParams, transaction, batchSize)) @@ -35,15 +35,15 @@ public static int BulkInsert(this IDbConnection connection, st /// /// Efficiently inserts multiple rows, in batches as necessary. /// - public static Task BulkInsertAsync(this IDbConnection connection, string sql, IEnumerable insertParams, IDbTransaction transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) + public static Task BulkInsertAsync(this IDbConnection connection, string sql, IEnumerable insertParams, IDbTransaction? transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) { - return connection.BulkInsertAsync(sql, (object) null, insertParams, transaction, batchSize, cancellationToken); + return connection.BulkInsertAsync(sql, (object?) null, insertParams, transaction, batchSize, cancellationToken); } /// /// Efficiently inserts multiple rows, in batches as necessary. /// - public static async Task BulkInsertAsync(this IDbConnection connection, string sql, TCommon commonParam, IEnumerable insertParams, IDbTransaction transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task BulkInsertAsync(this IDbConnection connection, string sql, TCommon? commonParam, IEnumerable insertParams, IDbTransaction? transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) { int rowCount = 0; foreach (var commandDefinition in GetBulkInsertCommands(sql, commonParam, insertParams, transaction, batchSize, cancellationToken)) @@ -54,15 +54,15 @@ public static int BulkInsert(this IDbConnection connection, st /// /// Gets the Dapper CommandDefinitions used by BulkInsert and BulkInsertAsync. /// - public static IEnumerable GetBulkInsertCommands(string sql, IEnumerable insertParams, IDbTransaction transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) + public static IEnumerable GetBulkInsertCommands(string sql, IEnumerable insertParams, IDbTransaction? transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) { - return GetBulkInsertCommands(sql, (object) null, insertParams, transaction, batchSize, cancellationToken); + return GetBulkInsertCommands(sql, (object?) null, insertParams, transaction, batchSize, cancellationToken); } /// /// Gets the Dapper CommandDefinitions used by BulkInsert and BulkInsertAsync. /// - public static IEnumerable GetBulkInsertCommands(string sql, TCommon commonParam, IEnumerable insertParams, IDbTransaction transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) + public static IEnumerable GetBulkInsertCommands(string sql, TCommon? commonParam, IEnumerable insertParams, IDbTransaction? transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) { if (sql == null) throw new ArgumentNullException(nameof(sql)); @@ -81,7 +81,7 @@ public static int BulkInsert(this IDbConnection connection, st return YieldBulkInsertCommands(valuesClauseMatches[0], sql, commonParam, insertParams, transaction, batchSize, cancellationToken); } - private static IEnumerable YieldBulkInsertCommands(Match valuesClauseMatch, string sql, TCommon commonParam, IEnumerable insertParams, IDbTransaction transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) + private static IEnumerable YieldBulkInsertCommands(Match valuesClauseMatch, string sql, TCommon? commonParam, IEnumerable insertParams, IDbTransaction? transaction = null, int? batchSize = null, CancellationToken cancellationToken = default(CancellationToken)) { // identify SQL parts Group tupleMatch = valuesClauseMatch.Groups[1]; @@ -91,7 +91,7 @@ public static int BulkInsert(this IDbConnection connection, st // get common names and values string[] commonNames = ParamExtractor.GetNames(); - object[] commonValues = ParamExtractor.GetValues(commonParam); + object?[] commonValues = ParamExtractor.GetValues(commonParam); // get insert names and find insert parameters in tuple string[] insertNames = ParamExtractor.GetNames(); @@ -106,9 +106,9 @@ public static int BulkInsert(this IDbConnection connection, st Math.Max(1, (maxParamsPerBatch - commonNames.Length) / Math.Max(1, insertNames.Length)); // insert one batch at a time - string batchSql = null; + string? batchSql = null; int lastBatchCount = 0; - StringBuilder batchSqlBuilder = null; + StringBuilder? batchSqlBuilder = null; foreach (var insertParamBatch in EnumerateBatches(insertParams, actualBatchSize)) { // build the SQL for the batch @@ -167,9 +167,9 @@ private static class ParamExtractor { public static string[] GetNames() => s_names; - public static object[] GetValues(T param) + public static object?[] GetValues(T? param) { - var values = new object[s_getters.Length]; + var values = new object?[s_getters.Length]; if (param != null) { for (int index = 0; index < values.Length; index++) @@ -183,7 +183,7 @@ static ParamExtractor() #pragma warning restore CA1810 { var names = new List(); - var getters = new List>(); + var getters = new List>(); foreach (var property in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)) { var getter = TryCreateGetter(property); @@ -197,7 +197,7 @@ static ParamExtractor() s_getters = [.. getters]; } - private static Func TryCreateGetter(PropertyInfo property) + private static Func? TryCreateGetter(PropertyInfo property) { var getMethod = property.GetGetMethod(); var ownerType = property.DeclaringType; @@ -215,11 +215,11 @@ private static Func TryCreateGetter(PropertyInfo property) generator.Emit(OpCodes.Box, property.PropertyType); generator.Emit(OpCodes.Ret); - return (Func) dynamicGetMethod.CreateDelegate(typeof(Func)); + return (Func) dynamicGetMethod.CreateDelegate(typeof(Func)); } private static readonly string[] s_names; - private static readonly Func[] s_getters; + private static readonly Func[] s_getters; } private static IEnumerable> EnumerateBatches(IEnumerable items, int batchSize) diff --git a/src/Faithlife.Utility.Dapper/Faithlife.Utility.Dapper.csproj b/src/Faithlife.Utility.Dapper/Faithlife.Utility.Dapper.csproj index 0e80ac7..5f601fb 100644 --- a/src/Faithlife.Utility.Dapper/Faithlife.Utility.Dapper.csproj +++ b/src/Faithlife.Utility.Dapper/Faithlife.Utility.Dapper.csproj @@ -7,6 +7,7 @@ true true README.md + true diff --git a/tests/Faithlife.Utility.Dapper.Tests/BulkInsertUtilityTests.cs b/tests/Faithlife.Utility.Dapper.Tests/BulkInsertUtilityTests.cs index 443df4a..09d88cb 100644 --- a/tests/Faithlife.Utility.Dapper.Tests/BulkInsertUtilityTests.cs +++ b/tests/Faithlife.Utility.Dapper.Tests/BulkInsertUtilityTests.cs @@ -11,7 +11,7 @@ public void NullSql_Throws() { Assert.Throws(() => { - BulkInsertUtility.GetBulkInsertCommands(null, new[] { new { foo = 1 } }); + BulkInsertUtility.GetBulkInsertCommands(null!, new[] { new { foo = 1 } }); }); } @@ -29,7 +29,7 @@ public void NullInsertParams_Throws() { Assert.Throws(() => { - BulkInsertUtility.GetBulkInsertCommands("VALUES (@foo)...", default(object[])); + BulkInsertUtility.GetBulkInsertCommands("VALUES (@foo)...", default(object[])!); }); } @@ -84,7 +84,7 @@ public void MinimalInsert() var commands = BulkInsertUtility.GetBulkInsertCommands("INSERT INTO t (foo)VALUES(@foo)...;", new[] { new { foo = 1 } }).ToList(); commands.Count.Should().Be(1); commands[0].CommandText.Should().Be("INSERT INTO t (foo)VALUES(@foo_0);"); - var parameters = (DynamicParameters) commands[0].Parameters; + var parameters = (DynamicParameters) commands[0].Parameters!; parameters.ParameterNames.Single().Should().Be("foo_0"); ((SqlMapper.IParameterLookup) parameters)["foo_0"].Should().Be(1); } @@ -112,7 +112,7 @@ public void CommonAndInsertedParameters() var commands = BulkInsertUtility.GetBulkInsertCommands("VALUES (@a, @b, @c, @d)...", new { a = 1, b = 2 }, new[] { new { c = 3, d = 4 }, new { c = 5, d = 6 } }).ToList(); commands.Count.Should().Be(1); commands[0].CommandText.Should().Be("VALUES (@a, @b, @c_0, @d_0),(@a, @b, @c_1, @d_1)"); - var parameters = (SqlMapper.IParameterLookup) commands[0].Parameters; + var parameters = (SqlMapper.IParameterLookup) commands[0].Parameters!; parameters["a"].Should().Be(1); parameters["b"].Should().Be(2); parameters["c_0"].Should().Be(3); @@ -129,7 +129,7 @@ public void EightRowsInThreeBatches() commands[0].CommandText.Should().Be("VALUES(@foo_0),(@foo_1),(@foo_2)"); commands[1].CommandText.Should().Be("VALUES(@foo_0),(@foo_1),(@foo_2)"); commands[2].CommandText.Should().Be("VALUES(@foo_0),(@foo_1)"); - ((SqlMapper.IParameterLookup) commands[2].Parameters)["foo_1"].Should().Be(7); + ((SqlMapper.IParameterLookup) commands[2].Parameters!)["foo_1"].Should().Be(7); } [Fact] @@ -177,7 +177,7 @@ public void NoParameterNameValidation() var commands = BulkInsertUtility.GetBulkInsertCommands("VALUES (@a, @b, @c, @d)...", new { e = 1, f = 2 }, new[] { new { g = 3, h = 4 }, new { g = 5, h = 6 } }).ToList(); commands.Count.Should().Be(1); commands[0].CommandText.Should().Be("VALUES (@a, @b, @c, @d),(@a, @b, @c, @d)"); - var parameters = (SqlMapper.IParameterLookup) commands[0].Parameters; + var parameters = (SqlMapper.IParameterLookup) commands[0].Parameters!; parameters["e"].Should().Be(1); parameters["f"].Should().Be(2); parameters["g_0"].Should().Be(3); @@ -192,7 +192,7 @@ public void ComplexValues() var commands = BulkInsertUtility.GetBulkInsertCommands("VALUES (@a + (@d * @c) -\r\n\t@d)...", new { a = 1, b = 2 }, new[] { new { c = 3, d = 4 }, new { c = 5, d = 6 } }).ToList(); commands.Count.Should().Be(1); commands[0].CommandText.Should().Be("VALUES (@a + (@d_0 * @c_0) -\r\n\t@d_0),(@a + (@d_1 * @c_1) -\r\n\t@d_1)"); - var parameters = (SqlMapper.IParameterLookup) commands[0].Parameters; + var parameters = (SqlMapper.IParameterLookup) commands[0].Parameters!; parameters["a"].Should().Be(1); parameters["b"].Should().Be(2); parameters["c_0"].Should().Be(3); From 7a2c69dce58dc79768cd84edeb41e41968b92fb1 Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 16:15:29 -0700 Subject: [PATCH 10/11] Rename .NET library props managed sections --- Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index db55429..2635a9c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,14 +7,14 @@ - + true true true - + From df3e90c5b60e9f24223feee9b6a229c4ee704564 Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Mon, 25 May 2026 16:23:23 -0700 Subject: [PATCH 11/11] Style nits in props files, gitignore --- .gitignore | 6 ------ Directory.Build.props | 1 + Directory.Packages.props | 14 +++++++------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index e83df5a..7ec75c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,3 @@ - -*.ncrunchproject -*.ncrunchsolution -launchSettings.json -nCrunchTemp* - # DO NOT EDIT: gitignore-common convention .DS_Store Thumbs.db diff --git a/Directory.Build.props b/Directory.Build.props index 8828676..696a49c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,6 +7,7 @@ Faithlife DapperUtility + 14.0 diff --git a/Directory.Packages.props b/Directory.Packages.props index 2635a9c..c1c4231 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,4 +1,11 @@ + + + true + true + true + + @@ -7,13 +14,6 @@ - - - true - true - true - -