Skip to content

Commit 21fe004

Browse files
Temp
1 parent 8a6b02f commit 21fe004

20 files changed

Lines changed: 153 additions & 137 deletions

File tree

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,8 @@ dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
5656
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
5757
dotnet_style_predefined_type_for_member_access = true:suggestion
5858

59+
# IDE0090: Use 'new(...)'
60+
dotnet_diagnostic.IDE0090.severity = none
61+
5962
[*.{csproj,proj,targets}]
6063
indent_size = 2

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,8 @@
99

1010
namespace PhenX.EntityFrameworkCore.BulkInsert.MySql;
1111

12-
internal class MySqlBulkInsertProvider : BulkInsertProviderBase<MySqlServerDialectBuilder, MySqlBulkInsertOptions>
12+
internal class MySqlBulkInsertProvider(ILogger<MySqlBulkInsertProvider>? logger = null) : BulkInsertProviderBase<MySqlServerDialectBuilder, MySqlBulkInsertOptions>(logger)
1313
{
14-
public MySqlBulkInsertProvider(ILogger<MySqlBulkInsertProvider>? logger = null) : base(logger)
15-
{
16-
}
17-
1814
//language=sql
1915
/// <inheritdoc />
2016
protected override string AddTableCopyBulkInsertId => $"ALTER TABLE {{0}} ADD {BulkInsertId} INT AUTO_INCREMENT PRIMARY KEY;";
@@ -26,13 +22,13 @@ public MySqlBulkInsertProvider(ILogger<MySqlBulkInsertProvider>? logger = null)
2622
protected override MySqlBulkInsertOptions CreateDefaultOptions() => new();
2723

2824
/// <inheritdoc />
29-
public override IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
25+
protected override IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
3026
bool sync,
3127
DbContext context,
3228
TableMetadata tableInfo,
3329
IEnumerable<T> entities,
34-
BulkInsertOptions options,
35-
OnConflictOptions? onConflict = null,
30+
MySqlBulkInsertOptions options,
31+
OnConflictOptions<T>? onConflict = null,
3632
CancellationToken ctk = default)
3733
{
3834
throw new NotSupportedException("Provider does not support returning entities.");

src/PhenX.EntityFrameworkCore.BulkInsert.PostgreSql/PostgreSqlBulkInsertProvider.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,8 @@
1313
namespace PhenX.EntityFrameworkCore.BulkInsert.PostgreSql;
1414

1515
[UsedImplicitly]
16-
internal class PostgreSqlBulkInsertProvider : BulkInsertProviderBase<PostgreSqlDialectBuilder, BulkInsertOptions>
16+
internal class PostgreSqlBulkInsertProvider(ILogger<PostgreSqlBulkInsertProvider>? logger = null) : BulkInsertProviderBase<PostgreSqlDialectBuilder, BulkInsertOptions>(logger)
1717
{
18-
public PostgreSqlBulkInsertProvider(ILogger<PostgreSqlBulkInsertProvider>? logger = null) : base(logger)
19-
{
20-
}
21-
2218
//language=sql
2319
/// <inheritdoc />
2420
protected override string AddTableCopyBulkInsertId => $"ALTER TABLE {{0}} ADD COLUMN {BulkInsertId} SERIAL PRIMARY KEY;";

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@
1111
namespace PhenX.EntityFrameworkCore.BulkInsert.SqlServer;
1212

1313
[UsedImplicitly]
14-
internal class SqlServerBulkInsertProvider : BulkInsertProviderBase<SqlServerDialectBuilder, SqlServerBulkInsertOptions>
14+
internal class SqlServerBulkInsertProvider(ILogger<SqlServerBulkInsertProvider>? logger = null) : BulkInsertProviderBase<SqlServerDialectBuilder, SqlServerBulkInsertOptions>(logger)
1515
{
16-
public SqlServerBulkInsertProvider(ILogger<SqlServerBulkInsertProvider>? logger = null) : base(logger)
17-
{
18-
}
1916

2017
//language=sql
2118
/// <inheritdoc />

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@
1313
namespace PhenX.EntityFrameworkCore.BulkInsert.Sqlite;
1414

1515
[UsedImplicitly]
16-
internal class SqliteBulkInsertProvider : BulkInsertProviderBase<SqliteDialectBuilder, BulkInsertOptions>
16+
internal class SqliteBulkInsertProvider(ILogger<SqliteBulkInsertProvider>? logger = null) : BulkInsertProviderBase<SqliteDialectBuilder, BulkInsertOptions>(logger)
1717
{
18-
public SqliteBulkInsertProvider(ILogger<SqliteBulkInsertProvider>? logger = null) : base(logger)
19-
{
20-
}
2118

2219
/// <inheritdoc />
2320
protected override string BulkInsertId => "rowid";

src/PhenX.EntityFrameworkCore.BulkInsert/Abstractions/IBulkInsertProvider.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ internal IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
2020
TableMetadata tableInfo,
2121
IEnumerable<T> entities,
2222
BulkInsertOptions options,
23-
OnConflictOptions? onConflict = null,
23+
OnConflictOptions<T>? onConflict = null,
2424
CancellationToken ctk = default
2525
) where T : class;
2626

@@ -33,7 +33,7 @@ internal Task BulkInsert<T>(
3333
TableMetadata tableInfo,
3434
IEnumerable<T> entities,
3535
BulkInsertOptions options,
36-
OnConflictOptions? onConflict = null,
36+
OnConflictOptions<T>? onConflict = null,
3737
CancellationToken ctk = default
3838
) where T : class;
3939

@@ -42,5 +42,5 @@ internal Task BulkInsert<T>(
4242
/// <summary>
4343
/// Make the default options for the provider, can be a subclass of <see cref="BulkInsertOptions"/>.
4444
/// </summary>
45-
internal BulkInsertOptions InternalCreateDefaultOptions();
45+
internal BulkInsertOptions CreateDefaultOptions();
4646
}

src/PhenX.EntityFrameworkCore.BulkInsert/BulkInsertOptionsExtension.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Microsoft.EntityFrameworkCore.Infrastructure;
1+
using Microsoft.EntityFrameworkCore.Infrastructure;
22
using Microsoft.Extensions.DependencyInjection;
33

44
using PhenX.EntityFrameworkCore.BulkInsert.Abstractions;
@@ -20,11 +20,8 @@ public void Validate(IDbContextOptions options)
2020
{
2121
}
2222

23-
private class BulkInsertOptionsExtensionInfo : DbContextOptionsExtensionInfo
23+
private class BulkInsertOptionsExtensionInfo(IDbContextOptionsExtension extension) : DbContextOptionsExtensionInfo(extension)
2424
{
25-
public BulkInsertOptionsExtensionInfo(IDbContextOptionsExtension extension)
26-
: base(extension) { }
27-
2825
/// <inheritdoc />
2926
public override int GetServiceProviderHashCode() => 0;
3027

src/PhenX.EntityFrameworkCore.BulkInsert/BulkInsertProviderBase.cs

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,32 @@
44
using Microsoft.EntityFrameworkCore.Storage;
55
using Microsoft.Extensions.Logging;
66

7-
using PhenX.EntityFrameworkCore.BulkInsert.Abstractions;
87
using PhenX.EntityFrameworkCore.BulkInsert.Dialect;
98
using PhenX.EntityFrameworkCore.BulkInsert.Extensions;
109
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
1110
using PhenX.EntityFrameworkCore.BulkInsert.Options;
1211

1312
namespace PhenX.EntityFrameworkCore.BulkInsert;
1413

15-
internal abstract class BulkInsertProviderBase<TDialect, TOptions>(ILogger<BulkInsertProviderBase<TDialect, TOptions>>? logger = null) : IBulkInsertProvider
14+
internal abstract class BulkInsertProviderBase<TDialect, TOptions>(ILogger? logger = null) : BulkInsertProviderUntyped<TDialect, TOptions>
1615
where TDialect : SqlDialectBuilder, new()
1716
where TOptions : BulkInsertOptions, new()
1817
{
19-
protected readonly TDialect SqlDialect = new();
20-
2118
protected virtual string BulkInsertId => "_bulk_insert_id";
2219

2320
protected abstract string AddTableCopyBulkInsertId { get; }
2421

2522
protected virtual string GetTempTableName(string tableName) => $"_temp_bulk_insert_{tableName}";
2623

27-
SqlDialectBuilder IBulkInsertProvider.SqlDialect => SqlDialect;
28-
29-
public BulkInsertOptions InternalCreateDefaultOptions() => CreateDefaultOptions();
30-
31-
/// <summary>
32-
/// Create the default options for the provider, can be a subclass of <see cref="BulkInsertOptions"/>.
33-
/// </summary>
34-
protected abstract TOptions CreateDefaultOptions();
35-
36-
public virtual async IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
24+
protected override async IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
3725
bool sync,
3826
DbContext context,
3927
TableMetadata tableInfo,
4028
IEnumerable<T> entities,
41-
BulkInsertOptions options,
42-
OnConflictOptions? onConflict,
29+
TOptions options,
30+
OnConflictOptions<T>? onConflict,
4331
[EnumeratorCancellation] CancellationToken ctk) where T : class
4432
{
45-
if (options is not TOptions providerOptions)
46-
{
47-
throw new InvalidOperationException($"Invalid options type: {options.GetType().Name}. Expected: {typeof(TOptions).Name}");
48-
}
49-
5033
using var activity = Telemetry.ActivitySource.StartActivity("BulkInsertReturnEntities");
5134
activity?.AddTag("tableName", tableInfo.TableName);
5235
activity?.AddTag("synchronous", sync);
@@ -59,10 +42,10 @@ public virtual async IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
5942
Log.UsingTempTablToReturnData(logger);
6043
}
6144

62-
var tableName = await PerformBulkInsertAsync(sync, context, tableInfo, entities, providerOptions, tempTableRequired: true, ctk: ctk);
45+
var tableName = await PerformBulkInsertAsync(sync, context, tableInfo, entities, options, tempTableRequired: true, ctk: ctk);
6346

6447
var result =
65-
await CopyFromTempTableAsync<T, T>(sync, context, tableInfo, tableName, true, providerOptions, onConflict, ctk: ctk)
48+
await CopyFromTempTableAsync<T, T>(sync, context, tableInfo, tableName, true, options, onConflict, ctk: ctk)
6649
?? throw new InvalidOperationException("Copy returns null enumerable.");
6750

6851
await foreach (var item in result.WithCancellation(ctk))
@@ -79,20 +62,15 @@ await CopyFromTempTableAsync<T, T>(sync, context, tableInfo, tableName, true, pr
7962
}
8063
}
8164

82-
public virtual async Task BulkInsert<T>(
65+
protected override async Task BulkInsert<T>(
8366
bool sync,
8467
DbContext context,
8568
TableMetadata tableInfo,
8669
IEnumerable<T> entities,
87-
BulkInsertOptions options,
88-
OnConflictOptions? onConflict,
70+
TOptions options,
71+
OnConflictOptions<T>? onConflict,
8972
CancellationToken ctk) where T : class
9073
{
91-
if (options is not TOptions providerOptions)
92-
{
93-
throw new InvalidOperationException($"Invalid options type: {options.GetType().Name}. Expected: {typeof(TOptions).Name}");
94-
}
95-
9674
using var activity = Telemetry.ActivitySource.StartActivity("BulkInsert");
9775
activity?.AddTag("tableName", tableInfo.TableName);
9876
activity?.AddTag("synchronous", sync);
@@ -107,9 +85,9 @@ public virtual async Task BulkInsert<T>(
10785
Log.UsingTempTableToResolveConflicts(logger);
10886
}
10987

110-
var tableName = await PerformBulkInsertAsync(sync, context, tableInfo, entities, providerOptions, tempTableRequired: true, ctk: ctk);
88+
var tableName = await PerformBulkInsertAsync(sync, context, tableInfo, entities, options, tempTableRequired: true, ctk: ctk);
11189

112-
await CopyFromTempTableAsync<T, T>(sync, context, tableInfo, tableName, false, providerOptions, onConflict, ctk);
90+
await CopyFromTempTableAsync<T, T>(sync, context, tableInfo, tableName, false, options, onConflict, ctk);
11391
}
11492
else
11593
{
@@ -118,7 +96,7 @@ public virtual async Task BulkInsert<T>(
11896
Log.UsingDirectInsert(logger);
11997
}
12098

121-
await PerformBulkInsertAsync(sync, context, tableInfo, entities, providerOptions, tempTableRequired: false, ctk: ctk);
99+
await PerformBulkInsertAsync(sync, context, tableInfo, entities, options, tempTableRequired: false, ctk: ctk);
122100
}
123101

124102
// Commit the transaction if we own them.
@@ -207,7 +185,7 @@ protected virtual async Task AddBulkInsertIdColumn<T>(
207185
string tempTableName,
208186
bool returnData,
209187
TOptions options,
210-
OnConflictOptions? onConflict,
188+
OnConflictOptions<T>? onConflict,
211189
CancellationToken ctk) where T : class where TResult : class
212190
{
213191
var query =
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
using PhenX.EntityFrameworkCore.BulkInsert.Abstractions;
4+
using PhenX.EntityFrameworkCore.BulkInsert.Dialect;
5+
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
6+
using PhenX.EntityFrameworkCore.BulkInsert.Options;
7+
8+
namespace PhenX.EntityFrameworkCore.BulkInsert;
9+
10+
internal abstract class BulkInsertProviderUntyped<TDialect, TOptions> : IBulkInsertProvider
11+
where TDialect : SqlDialectBuilder, new()
12+
where TOptions : BulkInsertOptions, new()
13+
{
14+
protected readonly TDialect SqlDialect = new();
15+
16+
SqlDialectBuilder IBulkInsertProvider.SqlDialect => SqlDialect;
17+
18+
BulkInsertOptions IBulkInsertProvider.CreateDefaultOptions() => CreateDefaultOptions();
19+
20+
/// <summary>
21+
/// Create the default options for the provider, can be a subclass of <see cref="BulkInsertOptions"/>.
22+
/// </summary>
23+
protected abstract TOptions CreateDefaultOptions();
24+
25+
public IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
26+
bool sync,
27+
DbContext context,
28+
TableMetadata tableInfo,
29+
IEnumerable<T> entities,
30+
BulkInsertOptions options,
31+
OnConflictOptions<T>? onConflict,
32+
CancellationToken ctk) where T : class
33+
{
34+
if (options is not TOptions providerOptions)
35+
{
36+
throw new InvalidOperationException($"Invalid options type: {options.GetType().Name}. Expected: {typeof(TOptions).Name}");
37+
}
38+
39+
return BulkInsertReturnEntities(sync, context, tableInfo, entities, providerOptions, onConflict, ctk);
40+
}
41+
42+
protected abstract IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
43+
bool sync,
44+
DbContext context,
45+
TableMetadata tableInfo,
46+
IEnumerable<T> entities,
47+
TOptions options,
48+
OnConflictOptions<T>? onConflict,
49+
CancellationToken ctk) where T : class;
50+
51+
public Task BulkInsert<T>(
52+
bool sync,
53+
DbContext context,
54+
TableMetadata tableInfo,
55+
IEnumerable<T> entities,
56+
BulkInsertOptions options,
57+
OnConflictOptions<T>? onConflict,
58+
CancellationToken ctk) where T : class
59+
{
60+
if (options is not TOptions providerOptions)
61+
{
62+
throw new InvalidOperationException($"Invalid options type: {options.GetType().Name}. Expected: {typeof(TOptions).Name}");
63+
}
64+
65+
return BulkInsert(sync, context, tableInfo, entities, providerOptions, onConflict, ctk);
66+
}
67+
68+
protected abstract Task BulkInsert<T>(
69+
bool sync,
70+
DbContext context,
71+
TableMetadata tableInfo,
72+
IEnumerable<T> entities,
73+
TOptions options,
74+
OnConflictOptions<T>? onConflict,
75+
CancellationToken ctk) where T : class;
76+
}

src/PhenX.EntityFrameworkCore.BulkInsert/Dialect/SqlDialectBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public string QuoteTableName(string? schema, string tableName)
154154
/// <summary>
155155
/// Gets column names for the insert statement, from an object initializer.
156156
/// </summary>
157-
protected string[] GetColumns<T>(TableMetadata table, Expression<Func<T, object>> columns)
157+
protected static string[] GetColumns<T>(TableMetadata table, Expression<Func<T, object>> columns)
158158
{
159159
return columns.Body switch
160160
{

0 commit comments

Comments
 (0)