Skip to content

Commit a317c64

Browse files
Merge branch 'master' of github.com:SebastianStehle/PhenX.EntityFrameworkCore.BulkInsert into metadata
# Conflicts: # src/PhenX.EntityFrameworkCore.BulkInsert.Sqlite/SqliteBulkInsertProvider.cs # src/PhenX.EntityFrameworkCore.BulkInsert/BulkInsertProviderBase.cs
2 parents c83bf72 + bfa007e commit a317c64

36 files changed

Lines changed: 459 additions & 237 deletions

src/PhenX.EntityFrameworkCore.BulkInsert.MySql/MySqlBulkInsertProvider.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ public MySqlBulkInsertProvider(ILogger<MySqlBulkInsertProvider>? logger = null)
2626
/// <inheritdoc />
2727
protected override string GetTempTableName(string tableName) => $"#_temp_bulk_insert_{tableName}";
2828

29+
/// <inheritdoc />
30+
public override Task<List<T>> BulkInsertReturnEntities<T>(
31+
bool sync,
32+
DbContext context,
33+
TableMetadata tableInfo,
34+
IEnumerable<T> entities,
35+
BulkInsertOptions options,
36+
OnConflictOptions? onConflict = null,
37+
CancellationToken ctk = default)
38+
{
39+
throw new NotSupportedException("Provider does not support returning entities.");
40+
}
41+
2942
/// <inheritdoc />
3043
protected override async Task BulkInsert<T>(
3144
bool sync,
@@ -39,11 +52,16 @@ CancellationToken ctk
3952
)
4053
{
4154
var connection = (MySqlConnection)context.Database.GetDbConnection();
42-
var sqlTransaction = context.Database.CurrentTransaction!.GetDbTransaction() as MySqlTransaction;
55+
var sqlTransaction = context.Database.CurrentTransaction!.GetDbTransaction()
56+
?? throw new InvalidOperationException("No open transaction found.");
57+
if (sqlTransaction is not MySqlTransaction mySqlTransaction)
58+
{
59+
throw new InvalidOperationException($"Invalid transaction foud, got {sqlTransaction.GetType()}.");
60+
}
4361

44-
var bulkCopy = new MySqlBulkCopy(connection, sqlTransaction);
62+
var bulkCopy = new MySqlBulkCopy(connection, mySqlTransaction);
4563
bulkCopy.DestinationTableName = tableName;
46-
bulkCopy.BulkCopyTimeout = 60;
64+
bulkCopy.BulkCopyTimeout = options.GetCopyTimeoutInSeconds();
4765

4866
var sourceOrdinal = 0;
4967
foreach (var prop in properties)
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using Microsoft.EntityFrameworkCore;
2-
using Microsoft.EntityFrameworkCore.Infrastructure;
2+
3+
using PhenX.EntityFrameworkCore.BulkInsert.Extensions;
34

45
namespace PhenX.EntityFrameworkCore.BulkInsert.MySql;
56

67
/// <summary>
7-
/// DbContext options extension for SQL Server.
8+
/// DbContext options extension for MySql.
89
/// </summary>
910
public static class MySqlDbContextOptionsExtensions
1011
{
@@ -13,10 +14,6 @@ public static class MySqlDbContextOptionsExtensions
1314
/// </summary>
1415
public static DbContextOptionsBuilder UseBulkInsertMySql(this DbContextOptionsBuilder optionsBuilder)
1516
{
16-
var extension = optionsBuilder.Options.FindExtension<BulkInsertOptionsExtension<MySqlBulkInsertProvider>>() ?? new BulkInsertOptionsExtension<MySqlBulkInsertProvider>();
17-
18-
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
19-
20-
return optionsBuilder;
17+
return optionsBuilder.UseProvider<MySqlBulkInsertProvider>();
2118
}
2219
}

src/PhenX.EntityFrameworkCore.BulkInsert.MySql/MySqlDialectBuilder.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ internal class MySqlServerDialectBuilder : SqlDialectBuilder
1414

1515
protected override bool SupportsMoveRows => false;
1616

17-
public override bool SupportsReturning => false;
18-
1917
protected override void AppendConflictCondition<T>(StringBuilder sql, OnConflictOptions<T> onConflictTyped)
2018
{
2119
throw new NotSupportedException("Conflict conditions are not supported in MYSQL");

src/PhenX.EntityFrameworkCore.BulkInsert.MySql/PhenX.EntityFrameworkCore.BulkInsert.MySql.csproj

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<ItemGroup>
4-
<None Include="..\..\images\icon.png" Link="icon.png">
5-
<PackagePath>\</PackagePath>
6-
<Pack>true</Pack>
7-
</None>
8-
<None Include="..\..\README.md" Link="README.md">
9-
<PackagePath>\</PackagePath>
10-
<Pack>true</Pack>
11-
</None>
12-
</ItemGroup>
13-
143
<ItemGroup>
154
<ProjectReference Include="..\PhenX.EntityFrameworkCore.BulkInsert\PhenX.EntityFrameworkCore.BulkInsert.csproj" />
165
</ItemGroup>
Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
using Microsoft.EntityFrameworkCore;
1+
using Microsoft.EntityFrameworkCore;
22
using Microsoft.EntityFrameworkCore.Infrastructure;
33

4+
using PhenX.EntityFrameworkCore.BulkInsert.Extensions;
5+
46
namespace PhenX.EntityFrameworkCore.BulkInsert.PostgreSql;
57

68
/// <summary>
@@ -13,10 +15,6 @@ public static class PostgreSqlDbContextOptionsExtensions
1315
/// </summary>
1416
public static DbContextOptionsBuilder UseBulkInsertPostgreSql(this DbContextOptionsBuilder optionsBuilder)
1517
{
16-
var extension = optionsBuilder.Options.FindExtension<BulkInsertOptionsExtension<PostgreSqlBulkInsertProvider>>() ?? new BulkInsertOptionsExtension<PostgreSqlBulkInsertProvider>();
17-
18-
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
19-
20-
return optionsBuilder;
18+
return optionsBuilder.UseProvider<PostgreSqlBulkInsertProvider>();
2119
}
2220
}

src/PhenX.EntityFrameworkCore.BulkInsert.SqlServer/SqlServerBulkInsertProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ protected override async Task BulkInsert<T>(
4545
using var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, sqlTransaction);
4646
bulkCopy.DestinationTableName = tableName;
4747
bulkCopy.BatchSize = options.BatchSize ?? 50_000;
48-
bulkCopy.BulkCopyTimeout = 60;
48+
bulkCopy.BulkCopyTimeout = options.GetCopyTimeoutInSeconds();
4949

5050
foreach (var prop in properties)
5151
{
52-
bulkCopy.ColumnMappings.Add(prop.Name, SqlDialect.Quote(prop.ColumnName));
52+
bulkCopy.ColumnMappings.Add(prop.Name, prop.ColumnName);
5353
}
5454

5555
if (sync)
Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
using Microsoft.EntityFrameworkCore;
1+
using Microsoft.EntityFrameworkCore;
22
using Microsoft.EntityFrameworkCore.Infrastructure;
33

4+
using PhenX.EntityFrameworkCore.BulkInsert.Extensions;
5+
46
namespace PhenX.EntityFrameworkCore.BulkInsert.SqlServer;
57

68
/// <summary>
@@ -13,10 +15,6 @@ public static class SqlServerDbContextOptionsExtensions
1315
/// </summary>
1416
public static DbContextOptionsBuilder UseBulkInsertSqlServer(this DbContextOptionsBuilder optionsBuilder)
1517
{
16-
var extension = optionsBuilder.Options.FindExtension<BulkInsertOptionsExtension<SqlServerBulkInsertProvider>>() ?? new BulkInsertOptionsExtension<SqlServerBulkInsertProvider>();
17-
18-
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
19-
20-
return optionsBuilder;
18+
return optionsBuilder.UseProvider<SqlServerBulkInsertProvider>();
2119
}
2220
}

src/PhenX.EntityFrameworkCore.BulkInsert.SqlServer/SqlServerDialectBuilder.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public override string BuildMoveDataSql<T>(
3030

3131
var q = new StringBuilder();
3232

33+
if (options.CopyGeneratedColumns)
34+
{
35+
q.AppendLine($"SET IDENTITY_INSERT {target} ON;");
36+
}
37+
3338
// Merge handling
3439
if (onConflict is OnConflictOptions<T> onConflictTyped && onConflictTyped.Match != null)
3540
{
@@ -78,11 +83,16 @@ public override string BuildMoveDataSql<T>(
7883

7984
q.AppendLine(";");
8085

86+
if (options.CopyGeneratedColumns)
87+
{
88+
q.AppendLine($"SET IDENTITY_INSERT {target} OFF;");
89+
}
90+
8191
return q.ToString();
8292
}
8393

8494
protected override string GetExcludedColumnName(string columnName)
8595
{
86-
return $"SOURCE.{Quote(columnName)}";
96+
return $"SOURCE.{columnName}";
8797
}
8898
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ private static SqliteType GetSqliteType(Type clrType)
8282
}
8383

8484
private DbCommand GetInsertCommand(DbContext context, TableMetadata tableInfo, string tableName,
85+
BulkInsertOptions options,
8586
int batchSize)
8687
{
87-
var columns = tableInfo.GetProperties(false);
88+
var columns = tableInfo.GetProperties(options.CopyGeneratedColumns);
8889
var cmd = context.Database.GetDbConnection().CreateCommand();
8990

9091
var sqliteColumns = columns
@@ -137,7 +138,7 @@ CancellationToken ctk
137138
var batchSize = options.BatchSize ?? 5;
138139
batchSize = Math.Min(batchSize, maxParams / properties.Count);
139140

140-
await using var insertCommand = GetInsertCommand(context, tableInfo, tableName, batchSize);
141+
await using var insertCommand = GetInsertCommand(context, tableInfo, tableName, options, batchSize);
141142

142143
foreach (var chunk in entities.Chunk(batchSize))
143144
{
@@ -150,7 +151,7 @@ CancellationToken ctk
150151
// Last chunk
151152
else
152153
{
153-
var partialInsertCommand = GetInsertCommand(context, tableInfo, tableName, chunk.Length);
154+
var partialInsertCommand = GetInsertCommand(context, tableInfo, tableName, options, chunk.Length);
154155

155156
FillValues(chunk, partialInsertCommand.Parameters, properties);
156157
await ExecuteCommand(sync, partialInsertCommand, ctk);

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Microsoft.EntityFrameworkCore;
22
using Microsoft.EntityFrameworkCore.Infrastructure;
33

4+
using PhenX.EntityFrameworkCore.BulkInsert.Extensions;
5+
46
namespace PhenX.EntityFrameworkCore.BulkInsert.Sqlite;
57

68
/// <summary>
@@ -13,9 +15,7 @@ public static class SqliteDbContextOptionsExtensions
1315
/// </summary>
1416
public static DbContextOptionsBuilder UseBulkInsertSqlite(this DbContextOptionsBuilder optionsBuilder)
1517
{
16-
var extension = optionsBuilder.Options.FindExtension<BulkInsertOptionsExtension<SqliteBulkInsertProvider>>() ?? new BulkInsertOptionsExtension<SqliteBulkInsertProvider>();
17-
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
18-
return optionsBuilder;
18+
return optionsBuilder.UseProvider<SqliteBulkInsertProvider>();
1919
}
2020
}
2121

0 commit comments

Comments
 (0)