1212
1313namespace PhenX . EntityFrameworkCore . BulkInsert ;
1414
15- internal abstract class BulkInsertProviderBase < TDialect > ( ILogger < BulkInsertProviderBase < TDialect > > ? logger = null ) : IBulkInsertProvider where TDialect : SqlDialectBuilder , new ( )
15+ internal abstract class BulkInsertProviderBase < TDialect , TOptions > ( ILogger < BulkInsertProviderBase < TDialect , TOptions > > ? logger = null ) : IBulkInsertProvider
16+ where TDialect : SqlDialectBuilder , new ( )
17+ where TOptions : BulkInsertOptions , new ( )
1618{
1719 protected readonly TDialect SqlDialect = new ( ) ;
1820
@@ -24,6 +26,13 @@ namespace PhenX.EntityFrameworkCore.BulkInsert;
2426
2527 SqlDialectBuilder IBulkInsertProvider . SqlDialect => SqlDialect ;
2628
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+
2736 public virtual async IAsyncEnumerable < T > BulkInsertReturnEntities < T > (
2837 bool sync ,
2938 DbContext context ,
@@ -33,6 +42,11 @@ public virtual async IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
3342 OnConflictOptions ? onConflict ,
3443 [ EnumeratorCancellation ] CancellationToken ctk ) where T : class
3544 {
45+ if ( options is not TOptions providerOptions )
46+ {
47+ throw new InvalidOperationException ( $ "Invalid options type: { options . GetType ( ) . Name } . Expected: { typeof ( TOptions ) . Name } ") ;
48+ }
49+
3650 using var activity = Telemetry . ActivitySource . StartActivity ( "BulkInsertReturnEntities" ) ;
3751 activity ? . AddTag ( "tableName" , tableInfo . TableName ) ;
3852 activity ? . AddTag ( "synchronous" , sync ) ;
@@ -45,10 +59,10 @@ public virtual async IAsyncEnumerable<T> BulkInsertReturnEntities<T>(
4559 Log . UsingTempTablToReturnData ( logger ) ;
4660 }
4761
48- var tableName = await PerformBulkInsertAsync ( sync , context , tableInfo , entities , options , tempTableRequired : true , ctk : ctk ) ;
62+ var tableName = await PerformBulkInsertAsync ( sync , context , tableInfo , entities , providerOptions , tempTableRequired : true , ctk : ctk ) ;
4963
5064 var result =
51- await CopyFromTempTableAsync < T , T > ( sync , context , tableInfo , tableName , true , options , onConflict , ctk : ctk )
65+ await CopyFromTempTableAsync < T , T > ( sync , context , tableInfo , tableName , true , providerOptions , onConflict , ctk : ctk )
5266 ?? throw new InvalidOperationException ( "Copy returns null enumerable." ) ;
5367
5468 await foreach ( var item in result . WithCancellation ( ctk ) )
@@ -74,6 +88,11 @@ public virtual async Task BulkInsert<T>(
7488 OnConflictOptions ? onConflict ,
7589 CancellationToken ctk ) where T : class
7690 {
91+ if ( options is not TOptions providerOptions )
92+ {
93+ throw new InvalidOperationException ( $ "Invalid options type: { options . GetType ( ) . Name } . Expected: { typeof ( TOptions ) . Name } ") ;
94+ }
95+
7796 using var activity = Telemetry . ActivitySource . StartActivity ( "BulkInsert" ) ;
7897 activity ? . AddTag ( "tableName" , tableInfo . TableName ) ;
7998 activity ? . AddTag ( "synchronous" , sync ) ;
@@ -88,9 +107,9 @@ public virtual async Task BulkInsert<T>(
88107 Log . UsingTempTableToResolveConflicts ( logger ) ;
89108 }
90109
91- var tableName = await PerformBulkInsertAsync ( sync , context , tableInfo , entities , options , tempTableRequired : true , ctk : ctk ) ;
110+ var tableName = await PerformBulkInsertAsync ( sync , context , tableInfo , entities , providerOptions , tempTableRequired : true , ctk : ctk ) ;
92111
93- await CopyFromTempTableAsync < T , T > ( sync , context , tableInfo , tableName , false , options , onConflict , ctk ) ;
112+ await CopyFromTempTableAsync < T , T > ( sync , context , tableInfo , tableName , false , providerOptions , onConflict , ctk ) ;
94113 }
95114 else
96115 {
@@ -99,7 +118,7 @@ public virtual async Task BulkInsert<T>(
99118 Log . UsingDirectInsert ( logger ) ;
100119 }
101120
102- await PerformBulkInsertAsync ( sync , context , tableInfo , entities , options , tempTableRequired : false , ctk : ctk ) ;
121+ await PerformBulkInsertAsync ( sync , context , tableInfo , entities , providerOptions , tempTableRequired : false , ctk : ctk ) ;
103122 }
104123
105124 // Commit the transaction if we own them.
@@ -116,7 +135,7 @@ private async Task<string> PerformBulkInsertAsync<T>(
116135 DbContext context ,
117136 TableMetadata tableInfo ,
118137 IEnumerable < T > entities ,
119- BulkInsertOptions options ,
138+ TOptions options ,
120139 bool tempTableRequired ,
121140 CancellationToken ctk ) where T : class
122141 {
@@ -149,7 +168,7 @@ protected abstract Task BulkInsert<T>(
149168 IEnumerable < T > entities ,
150169 string tableName ,
151170 IReadOnlyList < ColumnMetadata > columns ,
152- BulkInsertOptions options ,
171+ TOptions options ,
153172 CancellationToken ctk ) where T : class ;
154173
155174 protected async Task < string > CreateTableCopyAsync < T > (
@@ -187,7 +206,7 @@ protected virtual async Task AddBulkInsertIdColumn<T>(
187206 TableMetadata tableInfo ,
188207 string tempTableName ,
189208 bool returnData ,
190- BulkInsertOptions options ,
209+ TOptions options ,
191210 OnConflictOptions ? onConflict ,
192211 CancellationToken ctk ) where T : class where TResult : class
193212 {
0 commit comments