Skip to content

Commit c83bf72

Browse files
Metadata
1 parent 429f643 commit c83bf72

20 files changed

Lines changed: 385 additions & 242 deletions

File tree

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using MySqlConnector;
66

7+
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
78
using PhenX.EntityFrameworkCore.BulkInsert.Options;
89

910
namespace PhenX.EntityFrameworkCore.BulkInsert.MySql;
@@ -29,9 +30,10 @@ public MySqlBulkInsertProvider(ILogger<MySqlBulkInsertProvider>? logger = null)
2930
protected override async Task BulkInsert<T>(
3031
bool sync,
3132
DbContext context,
33+
TableMetadata tableInfo,
3234
IEnumerable<T> entities,
3335
string tableName,
34-
PropertyAccessor[] properties,
36+
IReadOnlyList<PropertyMetadata> properties,
3537
BulkInsertOptions options,
3638
CancellationToken ctk
3739
)

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using System.Text;
22

3-
using Microsoft.EntityFrameworkCore;
4-
using Microsoft.EntityFrameworkCore.Metadata;
5-
63
using PhenX.EntityFrameworkCore.BulkInsert.Dialect;
4+
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
75
using PhenX.EntityFrameworkCore.BulkInsert.Options;
86

97
namespace PhenX.EntityFrameworkCore.BulkInsert.MySql;
@@ -45,9 +43,9 @@ protected override void AppendOnConflictStatement(StringBuilder sql)
4543
sql.Append("ON DUPLICATE KEY");
4644
}
4745

48-
protected override void AppendDoNothing(StringBuilder sql, IProperty[] insertedProperties)
46+
protected override void AppendDoNothing(StringBuilder sql, IEnumerable<PropertyMetadata> insertedProperties)
4947
{
50-
var columnName = insertedProperties[0].GetColumnName();
48+
var columnName = insertedProperties.First().ColumnName;
5149

5250
sql.Append($"UPDATE {Quote(columnName)} = {GetExcludedColumnName(columnName)}");
5351
}

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
using Npgsql;
77

8+
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
89
using PhenX.EntityFrameworkCore.BulkInsert.Options;
910

1011
namespace PhenX.EntityFrameworkCore.BulkInsert.PostgreSql;
@@ -24,9 +25,9 @@ public PostgreSqlBulkInsertProvider(ILogger<PostgreSqlBulkInsertProvider>? logge
2425
/// <inheritdoc />
2526
protected override string AddTableCopyBulkInsertId => $"ALTER TABLE {{0}} ADD COLUMN {BulkInsertId} SERIAL PRIMARY KEY;";
2627

27-
private string GetBinaryImportCommand(DbContext context, Type entityType, string tableName)
28+
private static string GetBinaryImportCommand(TableMetadata tableInfo, string tableName)
2829
{
29-
var columns = GetQuotedColumns(context, entityType, false);
30+
var columns = tableInfo.GetProperties(false).Select(X => X.QuotedColumName);
3031

3132
return $"COPY {tableName} ({string.Join(", ", columns)}) FROM STDIN (FORMAT BINARY)";
3233
}
@@ -35,15 +36,16 @@ private string GetBinaryImportCommand(DbContext context, Type entityType, string
3536
protected override async Task BulkInsert<T>(
3637
bool sync,
3738
DbContext context,
39+
TableMetadata tableInfo,
3840
IEnumerable<T> entities,
3941
string tableName,
40-
PropertyAccessor[] properties,
42+
IReadOnlyList<PropertyMetadata> properties,
4143
BulkInsertOptions options,
42-
CancellationToken ctk) where T : class
44+
CancellationToken ctk)
4345
{
4446
var connection = (NpgsqlConnection)context.Database.GetDbConnection();
4547

46-
var importCommand = GetBinaryImportCommand(context, typeof(T), tableName);
48+
var importCommand = GetBinaryImportCommand(tableInfo, tableName);
4749

4850
var writer = sync
4951
// ReSharper disable once MethodHasAsyncOverloadWithCancellation

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.EntityFrameworkCore.Storage;
66
using Microsoft.Extensions.Logging;
77

8+
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
89
using PhenX.EntityFrameworkCore.BulkInsert.Options;
910

1011
namespace PhenX.EntityFrameworkCore.BulkInsert.SqlServer;
@@ -31,12 +32,12 @@ public SqlServerBulkInsertProvider(ILogger<SqlServerBulkInsertProvider>? logger
3132
protected override async Task BulkInsert<T>(
3233
bool sync,
3334
DbContext context,
35+
TableMetadata tableInfo,
3436
IEnumerable<T> entities,
3537
string tableName,
36-
PropertyAccessor[] properties,
38+
IReadOnlyList<PropertyMetadata> properties,
3739
BulkInsertOptions options,
38-
CancellationToken ctk
39-
)
40+
CancellationToken ctk)
4041
{
4142
var connection = (SqlConnection) context.Database.GetDbConnection();
4243
var sqlTransaction = context.Database.CurrentTransaction!.GetDbTransaction() as SqlTransaction;

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

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
using System.Linq.Expressions;
21
using System.Text;
32

4-
using Microsoft.EntityFrameworkCore;
5-
using Microsoft.EntityFrameworkCore.Metadata;
6-
73
using PhenX.EntityFrameworkCore.BulkInsert.Dialect;
4+
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
85
using PhenX.EntityFrameworkCore.BulkInsert.Options;
96

107
namespace PhenX.EntityFrameworkCore.BulkInsert.SqlServer;
@@ -17,29 +14,31 @@ internal class SqlServerDialectBuilder : SqlDialectBuilder
1714

1815
protected override bool SupportsMoveRows => false;
1916

20-
public override string BuildMoveDataSql<T>(DbContext context, string source,
17+
public override string BuildMoveDataSql<T>(
18+
TableMetadata source,
2119
string target,
22-
IProperty[] insertedProperties,
23-
IProperty[] properties,
24-
BulkInsertOptions options, OnConflictOptions? onConflict = null)
20+
IReadOnlyList<PropertyMetadata> insertedProperties,
21+
IReadOnlyList<PropertyMetadata> properties,
22+
BulkInsertOptions options,
23+
OnConflictOptions? onConflict = null)
2524
{
26-
var insertedColumns = insertedProperties.Select(p => Quote(p.GetColumnName())).ToArray();
25+
var insertedColumns = insertedProperties.Select(x => x.QuotedColumName);
2726
var insertedColumnList = string.Join(", ", insertedColumns);
2827

29-
var returnedColumns = properties.Select(p => $"INSERTED.{p.GetColumnName()} AS {p.GetColumnName()}");
28+
var returnedColumns = properties.Select(p => $"INSERTED.{p.ColumnName} AS {p.ColumnName}");
3029
var columnList = string.Join(", ", returnedColumns);
3130

3231
var q = new StringBuilder();
3332

3433
// Merge handling
3534
if (onConflict is OnConflictOptions<T> onConflictTyped && onConflictTyped.Match != null)
3635
{
37-
var matchColumns = GetColumns(context, onConflictTyped.Match);
36+
var matchColumns = GetColumns(source, onConflictTyped.Match);
3837
var matchOn = string.Join(" AND ",
3938
matchColumns.Select(col => $"TARGET.{col} = SOURCE.{col}"));
4039

4140
var updateSet = onConflictTyped.Update != null
42-
? string.Join(", ", GetUpdates(context, insertedProperties, onConflictTyped.Update))
41+
? string.Join(", ", GetUpdates(source, insertedProperties, onConflictTyped.Update))
4342
: null;
4443

4544
q.AppendLine($"MERGE INTO {target} AS TARGET");

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using Microsoft.EntityFrameworkCore;
77
using Microsoft.Extensions.Logging;
88

9-
using PhenX.EntityFrameworkCore.BulkInsert.Extensions;
9+
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
1010
using PhenX.EntityFrameworkCore.BulkInsert.Options;
1111

1212
namespace PhenX.EntityFrameworkCore.BulkInsert.Sqlite;
@@ -81,17 +81,17 @@ private static SqliteType GetSqliteType(Type clrType)
8181
throw new InvalidOperationException("Unknown Sqlite type for " + clrType);
8282
}
8383

84-
private DbCommand GetInsertCommand(DbContext context, Type entityType, string tableName,
84+
private DbCommand GetInsertCommand(DbContext context, TableMetadata tableInfo, string tableName,
8585
int batchSize)
8686
{
87-
var columns = context.GetProperties(entityType, false);
87+
var columns = tableInfo.GetProperties(false);
8888
var cmd = context.Database.GetDbConnection().CreateCommand();
8989

9090
var sqliteColumns = columns
9191
.Select(c => new
9292
{
93-
Name = c.GetColumnName(),
94-
Type = GetSqliteType(c.GetProviderClrType() ?? c.ClrType)
93+
Name = c.ColumnName,
94+
Type = GetSqliteType(c.ProviderClrType ?? c.ClrType)
9595
})
9696
.ToArray();
9797

@@ -125,18 +125,19 @@ private DbCommand GetInsertCommand(DbContext context, Type entityType, string ta
125125
protected override async Task BulkInsert<T>(
126126
bool sync,
127127
DbContext context,
128+
TableMetadata tableInfo,
128129
IEnumerable<T> entities,
129130
string tableName,
130-
PropertyAccessor[] properties,
131+
IReadOnlyList<PropertyMetadata> properties,
131132
BulkInsertOptions options,
132133
CancellationToken ctk
133134
) where T : class
134135
{
135136
const int maxParams = 1000;
136137
var batchSize = options.BatchSize ?? 5;
137-
batchSize = Math.Min(batchSize, maxParams / properties.Length);
138+
batchSize = Math.Min(batchSize, maxParams / properties.Count);
138139

139-
await using var insertCommand = GetInsertCommand(context, typeof(T), tableName, batchSize);
140+
await using var insertCommand = GetInsertCommand(context, tableInfo, tableName, batchSize);
140141

141142
foreach (var chunk in entities.Chunk(batchSize))
142143
{
@@ -149,7 +150,7 @@ CancellationToken ctk
149150
// Last chunk
150151
else
151152
{
152-
var partialInsertCommand = GetInsertCommand(context, typeof(T), tableName, chunk.Length);
153+
var partialInsertCommand = GetInsertCommand(context, tableInfo, tableName, chunk.Length);
153154

154155
FillValues(chunk, partialInsertCommand.Parameters, properties);
155156
await ExecuteCommand(sync, partialInsertCommand, ctk);
@@ -170,7 +171,7 @@ private static async Task ExecuteCommand(bool sync, DbCommand insertCommand, Can
170171
}
171172
}
172173

173-
private static void FillValues<T>(T[] chunk, DbParameterCollection parameters, PropertyAccessor[] properties) where T : class
174+
private static void FillValues<T>(T[] chunk, DbParameterCollection parameters, IReadOnlyList<PropertyMetadata> properties) where T : class
174175
{
175176
var index = 0;
176177
foreach (var entity in chunk)

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using Microsoft.EntityFrameworkCore;
22

3+
using PhenX.EntityFrameworkCore.BulkInsert.Dialect;
4+
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
35
using PhenX.EntityFrameworkCore.BulkInsert.Options;
46

57
namespace PhenX.EntityFrameworkCore.BulkInsert.Abstractions;
@@ -15,6 +17,7 @@ internal interface IBulkInsertProvider
1517
internal Task<List<T>> BulkInsertReturnEntities<T>(
1618
bool sync,
1719
DbContext context,
20+
TableMetadata tableInfo,
1821
IEnumerable<T> entities,
1922
BulkInsertOptions options,
2023
OnConflictOptions? onConflict = null,
@@ -27,9 +30,12 @@ internal Task<List<T>> BulkInsertReturnEntities<T>(
2730
internal Task BulkInsert<T>(
2831
bool sync,
2932
DbContext context,
33+
TableMetadata tableInfo,
3034
IEnumerable<T> entities,
3135
BulkInsertOptions options,
3236
OnConflictOptions? onConflict = null,
3337
CancellationToken ctk = default
3438
) where T : class;
39+
40+
SqlDialectBuilder SqlDialect { get; }
3541
}

0 commit comments

Comments
 (0)