Skip to content

Commit 9d16944

Browse files
Drop table.
1 parent ad0395d commit 9d16944

4 files changed

Lines changed: 78 additions & 15 deletions

File tree

src/PhenX.EntityFrameworkCore.BulkInsert.Sqlite/SqliteBulkInsertProvider.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ internal class SqliteBulkInsertProvider(ILogger<SqliteBulkInsertProvider>? logge
2020
/// <inheritdoc />
2121
protected override string BulkInsertId => "rowid";
2222

23-
//language=sql
2423
/// <inheritdoc />
2524
protected override string AddTableCopyBulkInsertId => "--"; // No need to add an ID column in SQLite
2625

26+
/// <inheritdoc />
27+
protected override string GetTempTableName(string tableName) => $"_temp_bulk_insert_test_entity_{Guid.NewGuid():N}";
28+
2729
/// <inheritdoc />
2830
protected override BulkInsertOptions CreateDefaultOptions() => new()
2931
{
@@ -116,6 +118,12 @@ private static DbCommand GetInsertCommand(
116118
return command;
117119
}
118120

121+
/// <inheritdoc />
122+
protected override Task DropTempTableAsync(bool sync, DbContext dbContext, string tableName)
123+
{
124+
return ExecuteAsync(sync, dbContext, $"DROP TABLE IF EXISTS {tableName}", default);
125+
}
126+
119127
/// <inheritdoc />
120128
protected override async Task BulkInsert<T>(
121129
bool sync,

src/PhenX.EntityFrameworkCore.BulkInsert/BulkInsertProviderBase.cs

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Runtime.CompilerServices;
2+
using System.Runtime.InteropServices;
23

34
using Microsoft.EntityFrameworkCore;
45
using Microsoft.EntityFrameworkCore.Storage;
@@ -43,14 +44,20 @@ protected override async IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
4344
}
4445

4546
var tableName = await PerformBulkInsertAsync(sync, context, tableInfo, entities, options, tempTableRequired: true, ctk: ctk);
47+
try
48+
{
49+
var result =
50+
await CopyFromTempTableAsync<T, T>(sync, context, tableInfo, tableName, true, options, onConflict, ctk: ctk)
51+
?? throw new InvalidOperationException("Copy returns null enumerable.");
4652

47-
var result =
48-
await CopyFromTempTableAsync<T, T>(sync, context, tableInfo, tableName, true, options, onConflict, ctk: ctk)
49-
?? throw new InvalidOperationException("Copy returns null enumerable.");
50-
51-
await foreach (var item in result.WithCancellation(ctk))
53+
await foreach (var item in result.WithCancellation(ctk))
54+
{
55+
yield return item;
56+
}
57+
}
58+
finally
5259
{
53-
yield return item;
60+
await PerformDropTempTableAsync(sync, context, tableName);
5461
}
5562

5663
// Commit the transaction if we own them.
@@ -71,6 +78,11 @@ protected override async Task BulkInsert<T>(
7178
OnConflictOptions<T>? onConflict,
7279
CancellationToken ctk) where T : class
7380
{
81+
if (entities.TryGetNonEnumeratedCount(out var count) && count == 0)
82+
{
83+
throw new InvalidOperationException("No entities to insert.");
84+
}
85+
7486
using var activity = Telemetry.ActivitySource.StartActivity("BulkInsert");
7587
activity?.AddTag("tableName", tableInfo.TableName);
7688
activity?.AddTag("synchronous", sync);
@@ -86,8 +98,14 @@ protected override async Task BulkInsert<T>(
8698
}
8799

88100
var tableName = await PerformBulkInsertAsync(sync, context, tableInfo, entities, options, tempTableRequired: true, ctk: ctk);
89-
90-
await CopyFromTempTableAsync<T, T>(sync, context, tableInfo, tableName, false, options, onConflict, ctk);
101+
try
102+
{
103+
await CopyFromTempTableAsync<T, T>(sync, context, tableInfo, tableName, false, options, onConflict, ctk);
104+
}
105+
finally
106+
{
107+
await PerformDropTempTableAsync(sync, context, tableName);
108+
}
91109
}
92110
else
93111
{
@@ -107,7 +125,6 @@ protected override async Task BulkInsert<T>(
107125
await connection.Close(sync, ctk);
108126
}
109127
}
110-
111128
private async Task<string> PerformBulkInsertAsync<T>(
112129
bool sync,
113130
DbContext context,
@@ -117,11 +134,6 @@ private async Task<string> PerformBulkInsertAsync<T>(
117134
bool tempTableRequired,
118135
CancellationToken ctk) where T : class
119136
{
120-
if (entities.TryGetNonEnumeratedCount(out var count) && count == 0)
121-
{
122-
throw new InvalidOperationException("No entities to insert.");
123-
}
124-
125137
var tableName = tempTableRequired
126138
? await CreateTableCopyAsync<T>(sync, context, options, tableInfo, ctk)
127139
: tableInfo.QuotedTableName;
@@ -208,6 +220,33 @@ protected virtual async Task AddBulkInsertIdColumn<T>(
208220
return null;
209221
}
210222

223+
private async Task PerformDropTempTableAsync(bool sync, DbContext dbContext, string tableName)
224+
{
225+
try
226+
{
227+
await DropTempTableAsync(sync, dbContext, tableName);
228+
}
229+
catch (Exception ex)
230+
{
231+
// The drop operation is not mandatory, therefore never fail the actual operation.
232+
if (logger != null)
233+
{
234+
Log.DropTemporaryTableFailed(logger, ex);
235+
}
236+
}
237+
}
238+
239+
/// <summary>
240+
/// Drops the temporary table manually if needed.
241+
/// </summary>
242+
/// <param name="sync">Indicates if the operation is synchronous.</param>
243+
/// <param name="dbContext">The context.</param>
244+
/// <param name="tableName">The table name.</param>
245+
protected virtual Task DropTempTableAsync(bool sync, DbContext dbContext, string tableName)
246+
{
247+
return Task.CompletedTask;
248+
}
249+
211250
protected static async Task ExecuteAsync(
212251
bool sync,
213252
DbContext context,

src/PhenX.EntityFrameworkCore.BulkInsert/BulkInsertProviderUntyped.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ public IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
3636
throw new InvalidOperationException($"Invalid options type: {options.GetType().Name}. Expected: {typeof(TOptions).Name}");
3737
}
3838

39+
if (entities.TryGetNonEnumeratedCount(out var count) && count == 0)
40+
{
41+
throw new InvalidOperationException("No entities to insert.");
42+
}
43+
3944
return BulkInsertReturnEntities(sync, context, tableInfo, entities, providerOptions, onConflict, ctk);
4045
}
4146

@@ -62,6 +67,11 @@ public Task BulkInsert<T>(
6267
throw new InvalidOperationException($"Invalid options type: {options.GetType().Name}. Expected: {typeof(TOptions).Name}");
6368
}
6469

70+
if (entities.TryGetNonEnumeratedCount(out var count) && count == 0)
71+
{
72+
throw new InvalidOperationException("No entities to insert.");
73+
}
74+
6575
return BulkInsert(sync, context, tableInfo, entities, providerOptions, onConflict, ctk);
6676
}
6777

src/PhenX.EntityFrameworkCore.BulkInsert/Log.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,10 @@ internal static partial class Log
2121
Level = LogLevel.Trace,
2222
Message = "Insert to table directly")]
2323
public static partial void UsingDirectInsert(ILogger logger);
24+
25+
[LoggerMessage(
26+
EventId = 1003,
27+
Level = LogLevel.Error,
28+
Message = "Failed to drop temporary table.")]
29+
public static partial void DropTemporaryTableFailed(ILogger logger, Exception exception);
2430
}

0 commit comments

Comments
 (0)