From 97b08c53b39c3bd1750091c013dba664eb2dde6d Mon Sep 17 00:00:00 2001 From: Kevin Petit Date: Tue, 17 Oct 2023 17:27:40 +0200 Subject: [PATCH] Use the correct table alias for the update statement used when a synchronize filter is defined. --- EFCore.BulkExtensions.Tests/EFCoreBulkTest.cs | 12 +++++++++++ .../EFCoreBulkTestAsync.cs | 20 +++++++++++++++---- .../SqlAdapters/SqlQueryBuilder.cs | 4 +++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/EFCore.BulkExtensions.Tests/EFCoreBulkTest.cs b/EFCore.BulkExtensions.Tests/EFCoreBulkTest.cs index 7601218c..c4923b7a 100644 --- a/EFCore.BulkExtensions.Tests/EFCoreBulkTest.cs +++ b/EFCore.BulkExtensions.Tests/EFCoreBulkTest.cs @@ -694,6 +694,18 @@ private static void RunInsertOrUpdateOrDelete(bool isBulk) var list = context.Items.Take(2).ToList(); Assert.True(list[0].Quantity != 0); Assert.True(list[1].Quantity == 0); + + // TEST Alias + context.Entries.Add(new Entry { Name = "Entry_InsertOrUpdateOrDelete" }); + context.SaveChanges(); + + int entriesCount = context.Entries.Count(); + + bulkConfigSoftDel.SetSynchronizeSoftDelete(a => new Entry { Name = "Entry_InsertOrUpdateOrDelete_Deleted" }); + context.BulkInsertOrUpdateOrDelete(new List { new Entry { Name = "Entry_InsertOrUpdateOrDelete_2" } }, bulkConfigSoftDel); + + Assert.Equal(entriesCount + 1, context.Entries.Count()); + Assert.True(context.Entries.Any(e => e.Name == "Entry_InsertOrUpdateOrDelete_Deleted")); } private static void RunUpdate(bool isBulk, SqlType sqlType) diff --git a/EFCore.BulkExtensions.Tests/EFCoreBulkTestAsync.cs b/EFCore.BulkExtensions.Tests/EFCoreBulkTestAsync.cs index 6d22846b..082f51fd 100644 --- a/EFCore.BulkExtensions.Tests/EFCoreBulkTestAsync.cs +++ b/EFCore.BulkExtensions.Tests/EFCoreBulkTestAsync.cs @@ -279,7 +279,7 @@ private static async Task RunInsertOrUpdateOrDeleteAsync(bool isBulk) await context.BulkInsertOrUpdateOrDeleteAsync(entities, bulkConfig); Assert.Equal(0, bulkConfig.StatsInfo?.StatsNumberInserted); Assert.Equal(EntitiesNumber / 2, bulkConfig.StatsInfo?.StatsNumberUpdated); - Assert.Equal((EntitiesNumber / 2) -1, bulkConfig.StatsInfo?.StatsNumberDeleted); + Assert.Equal((EntitiesNumber / 2) - 1, bulkConfig.StatsInfo?.StatsNumberDeleted); } else { @@ -304,11 +304,23 @@ private static async Task RunInsertOrUpdateOrDeleteAsync(bool isBulk) var bulkConfigSoftDel = new BulkConfig(); bulkConfigSoftDel.SetSynchronizeSoftDelete(a => new Item { Quantity = 0 }); // Instead of Deleting from DB it updates Quantity to 0 (usual usecase would be: IsDeleted to True) - context.BulkInsertOrUpdateOrDelete(new List { entities[1] }, bulkConfigSoftDel); + await context.BulkInsertOrUpdateOrDeleteAsync(new List { entities[1] }, bulkConfigSoftDel); var list = await context.Items.Take(2).ToListAsync(); Assert.True(list[0].Quantity != 0); - Assert.True(list[1].Quantity == 0); + Assert.True(list[1].Quantity == 0); + + // TEST Alias + await context.Entries.AddAsync(new Entry { Name = "Entry_InsertOrUpdateOrDelete" }); + await context.SaveChangesAsync(); + + int entriesCount = await contextRead.Entries.CountAsync(); + + bulkConfigSoftDel.SetSynchronizeSoftDelete(a => new Entry { Name = "Entry_InsertOrUpdateOrDelete_Deleted" }); + await context.BulkInsertOrUpdateOrDeleteAsync(new List { new Entry { Name = "Entry_InsertOrUpdateOrDelete_2" } }, bulkConfigSoftDel); + + Assert.Equal(entriesCount + 1, await contextRead.Entries.CountAsync()); + Assert.True(await context.Entries.AnyAsync(e => e.Name == "Entry_InsertOrUpdateOrDelete_Deleted")); } private static async Task RunUpdateAsync(bool isBulk, SqlType sqlType) @@ -358,7 +370,7 @@ private static async Task RunReadAsync() entities.Add(new Item { Name = "name " + i }); } - var bulkConfig = new BulkConfig { UpdateByProperties = new List { nameof(Item.Name) }}; + var bulkConfig = new BulkConfig { UpdateByProperties = new List { nameof(Item.Name) } }; await context.BulkReadAsync(entities, bulkConfig).ConfigureAwait(false); Assert.Equal(1, entities[0].ItemId); diff --git a/EFCore.BulkExtensions/SqlAdapters/SqlQueryBuilder.cs b/EFCore.BulkExtensions/SqlAdapters/SqlQueryBuilder.cs index 6ac1a13b..2d745a18 100644 --- a/EFCore.BulkExtensions/SqlAdapters/SqlQueryBuilder.cs +++ b/EFCore.BulkExtensions/SqlAdapters/SqlQueryBuilder.cs @@ -399,8 +399,10 @@ public static (string sql, IEnumerable parameters) MergeTable(DbConte var querable = context.Set().IgnoreQueryFilters().IgnoreAutoIncludes(); var expression = (Expression>)tableInfo.BulkConfig.SynchronizeSoftDelete; var (sqlOriginal, sqlParameters) = BatchUtil.GetSqlUpdate(querable, context, typeof(T), expression); + var databaseType = SqlAdaptersMapping.GetDatabaseType(); + var (tableAlias, _) = SqlAdaptersMapping.GetAdapterDialect().GetBatchSqlReformatTableAliasAndTopStatement(sqlOriginal, databaseType); - var sql = sqlOriginal.Replace("[i]", "T"); + var sql = sqlOriginal.Replace($"[{tableAlias}]", "T"); int indexFrom = sql.IndexOf(".") - 1; int indexTo = sql.IndexOf("\r\n") - indexFrom; softDeleteAssignment = sql.Substring(indexFrom, indexTo);