Skip to content

Commit b7b70e9

Browse files
Cleanup.
1 parent 656459a commit b7b70e9

8 files changed

Lines changed: 205 additions & 140 deletions

File tree

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@ public MySqlBulkInsertProvider(ILogger<MySqlBulkInsertProvider>? logger = null)
1515
{
1616
}
1717

18-
//language=sql
19-
/// <inheritdoc />
20-
protected override string CreateTableCopySql => "CREATE TEMPORARY TABLE {0} SELECT * FROM {1} WHERE 1 = 0;";
21-
2218
//language=sql
2319
/// <inheritdoc />
2420
protected override string AddTableCopyBulkInsertId => $"ALTER TABLE {{0}} ADD {BulkInsertId} INT AUTO_INCREMENT PRIMARY KEY;";
2521

2622
/// <inheritdoc />
2723
protected override string GetTempTableName(string tableName) => $"#_temp_bulk_insert_{tableName}";
2824

25+
protected override string CreateTableCopySql(string tempNameName, TableMetadata tableInfo, IReadOnlyList<PropertyMetadata> columns)
26+
{
27+
return $"CREATE TEMPORARY TABLE {tempNameName} SELECT * FROM {tableInfo.QuotedTableName} WHERE 1 = 0;";
28+
}
29+
2930
/// <inheritdoc />
3031
public override Task<List<T>> BulkInsertReturnEntities<T>(
3132
bool sync,

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Text;
2+
13
using JetBrains.Annotations;
24

35
using Microsoft.EntityFrameworkCore;
@@ -19,17 +21,23 @@ public PostgreSqlBulkInsertProvider(ILogger<PostgreSqlBulkInsertProvider>? logge
1921

2022
//language=sql
2123
/// <inheritdoc />
22-
protected override string CreateTableCopySql => "CREATE TEMPORARY TABLE {0} AS TABLE {1} WITH NO DATA;";
24+
protected override string AddTableCopyBulkInsertId => $"ALTER TABLE {{0}} ADD COLUMN {BulkInsertId} SERIAL PRIMARY KEY;";
2325

24-
//language=sql
2526
/// <inheritdoc />
26-
protected override string AddTableCopyBulkInsertId => $"ALTER TABLE {{0}} ADD COLUMN {BulkInsertId} SERIAL PRIMARY KEY;";
27+
protected override string CreateTableCopySql(string tempNameName, TableMetadata tableInfo, IReadOnlyList<PropertyMetadata> columns)
28+
{
29+
return $"CREATE TEMPORARY TABLE {tempNameName} AS TABLE {tableInfo.QuotedTableName} WITH NO DATA;";
30+
}
2731

2832
private static string GetBinaryImportCommand(TableMetadata tableInfo, string tableName)
2933
{
3034
var columns = tableInfo.GetProperties(false).Select(X => X.QuotedColumName);
3135

32-
return $"COPY {tableName} ({string.Join(", ", columns)}) FROM STDIN (FORMAT BINARY)";
36+
var sql = new StringBuilder();
37+
sql.Append($"COPY {tableName} (");
38+
sql.AppendColumns(tableInfo.GetProperties(false));
39+
sql.Append(") FROM STDIN (FORMAT BINARY)");
40+
return sql.ToString();
3341
}
3442

3543
/// <inheritdoc />

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Text;
2+
13
using JetBrains.Annotations;
24

35
using Microsoft.Data.SqlClient;
@@ -17,17 +19,23 @@ public SqlServerBulkInsertProvider(ILogger<SqlServerBulkInsertProvider>? logger
1719
{
1820
}
1921

20-
//language=sql
21-
/// <inheritdoc />
22-
protected override string CreateTableCopySql => "SELECT {2} INTO {0} FROM {1} WHERE 1 = 0;";
23-
2422
//language=sql
2523
/// <inheritdoc />
2624
protected override string AddTableCopyBulkInsertId => $"ALTER TABLE {{0}} ADD {BulkInsertId} INT IDENTITY PRIMARY KEY;";
2725

2826
/// <inheritdoc />
2927
protected override string GetTempTableName(string tableName) => $"#_temp_bulk_insert_{tableName}";
3028

29+
protected override string CreateTableCopySql(string templNameName, TableMetadata tableInfo, IReadOnlyList<PropertyMetadata> columns)
30+
{
31+
var sb = new StringBuilder();
32+
sb.Append("SELECT");
33+
sb.AppendJoin(", ", columns.Select(x => x.QuotedColumName));
34+
sb.Append($"INTO {templNameName} FROM {tableInfo.QuotedTableName} WHERE 1 = 0;");
35+
36+
return sb.ToString();
37+
}
38+
3139
/// <inheritdoc />
3240
protected override async Task BulkInsert<T>(
3341
bool sync,

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

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

3+
using Microsoft.Extensions.Primitives;
4+
35
using PhenX.EntityFrameworkCore.BulkInsert.Dialect;
46
using PhenX.EntityFrameworkCore.BulkInsert.Metadata;
57
using PhenX.EntityFrameworkCore.BulkInsert.Options;
@@ -18,16 +20,10 @@ public override string BuildMoveDataSql<T>(
1820
TableMetadata target,
1921
string source,
2022
IReadOnlyList<PropertyMetadata> insertedProperties,
21-
IReadOnlyList<PropertyMetadata> properties,
23+
IReadOnlyList<PropertyMetadata> returnedProperties,
2224
BulkInsertOptions options,
2325
OnConflictOptions? onConflict = null)
2426
{
25-
var insertedColumns = insertedProperties.Select(x => x.QuotedColumName);
26-
var insertedColumnList = string.Join(", ", insertedColumns);
27-
28-
var returnedColumns = properties.Select(p => $"INSERTED.{p.ColumnName} AS {p.ColumnName}");
29-
var columnList = string.Join(", ", returnedColumns);
30-
3127
var q = new StringBuilder();
3228

3329
if (options.CopyGeneratedColumns)
@@ -36,49 +32,76 @@ public override string BuildMoveDataSql<T>(
3632
}
3733

3834
// Merge handling
39-
if (onConflict is OnConflictOptions<T> onConflictTyped && onConflictTyped.Match != null)
35+
if (onConflict is OnConflictOptions<T> onConflictTyped)
4036
{
41-
var matchColumns = GetColumns(target, onConflictTyped.Match);
42-
var matchOn = string.Join(" AND ",
43-
matchColumns.Select(col => $"TARGET.{col} = SOURCE.{col}"));
44-
45-
var updateSet = onConflictTyped.Update != null
46-
? string.Join(", ", GetUpdates(target, insertedProperties, onConflictTyped.Update))
47-
: null;
37+
IEnumerable<string> matchColumns;
38+
if (onConflictTyped.Match != null)
39+
{
40+
matchColumns = GetColumns(target, onConflictTyped.Match);
41+
}
42+
else if (target.PrimaryKey.Count > 0)
43+
{
44+
matchColumns = target.PrimaryKey.Select(x => x.QuotedColumName);
45+
}
46+
else
47+
{
48+
throw new InvalidOperationException("Table has no primary key that can be used for conflict detection.");
49+
}
4850

4951
q.AppendLine($"MERGE INTO {target.QuotedTableName} AS TARGET");
50-
q.AppendLine(
51-
$"USING (SELECT {string.Join(", ", insertedColumns)} FROM {source}) AS SOURCE ({insertedColumnList})");
52-
q.AppendLine($"ON {matchOn}");
5352

54-
if (updateSet != null)
53+
q.Append("USING (SELECT ");
54+
q.AppendColumns(insertedProperties);
55+
q.Append($" FROM {source}) AS SOURCE (");
56+
q.AppendColumns(insertedProperties);
57+
q.AppendLine(")");
58+
59+
q.Append("ON ");
60+
q.AppendJoin($" AND ", matchColumns, (b, col) => b.Append($"TARGET.{col} = SOURCE.{col}"));
61+
q.AppendLine();
62+
63+
if (onConflictTyped.Update != null)
5564
{
56-
q.AppendLine($"WHEN MATCHED THEN UPDATE SET {updateSet}");
65+
q.AppendLine($"WHEN MATCHED THEN UPDATE SET ");
66+
q.AppendJoin(", ", GetUpdates(target, insertedProperties, onConflictTyped.Update));
67+
q.AppendLine();
5768
}
5869

59-
q.AppendLine(
60-
$"WHEN NOT MATCHED THEN INSERT ({insertedColumnList}) VALUES ({string.Join(", ", insertedColumns.Select(c => $"SOURCE.{c}"))})");
70+
q.Append($"WHEN NOT MATCHED THEN INSERT (");
71+
q.AppendColumns(insertedProperties);
72+
q.AppendLine(")");
73+
74+
q.Append("VALUES (");
75+
q.AppendJoin(", ", insertedProperties, (b, col) => b.Append($"SOURCE.{col.QuotedColumName}"));
76+
q.AppendLine(")");
6177

62-
if (columnList.Length != 0)
78+
if (returnedProperties.Count != 0)
6379
{
64-
q.AppendLine($"OUTPUT {columnList}");
80+
q.Append("OUTPUT ");
81+
q.AppendJoin($", ", returnedProperties, (b, col) => b.Append($"INSERTED.{col.QuotedColumName} AS {col.QuotedColumName}"));
82+
q.AppendLine();
6583
}
6684
}
6785

6886
// No conflict handling
6987
else
7088
{
71-
q.AppendLine($"INSERT INTO {target.QuotedTableName} ({insertedColumnList})");
89+
q.Append($"INSERT INTO {target.QuotedTableName} (");
90+
q.AppendColumns(insertedProperties);
91+
q.AppendLine(")");
7292

73-
if (columnList.Length != 0)
93+
if (returnedProperties.Count != 0)
7494
{
75-
q.AppendLine($"OUTPUT {columnList}");
95+
q.Append("OUTPUT ");
96+
q.AppendJoin($", ", returnedProperties, (b, col) => b.Append($"INSERTED.{col.QuotedColumName} AS {col.QuotedColumName}"));
97+
q.AppendLine();
7698
}
7799

78-
q.AppendLine($"""
79-
SELECT {insertedColumnList}
80-
FROM {source}
81-
""");
100+
q.Append("SELECT ");
101+
q.AppendColumns(insertedProperties);
102+
q.AppendLine();
103+
q.Append($"FROM {source}");
104+
q.AppendLine();
82105
}
83106

84107
q.AppendLine(";");
@@ -88,7 +111,8 @@ public override string BuildMoveDataSql<T>(
88111
q.AppendLine($"SET IDENTITY_INSERT {target.QuotedTableName} OFF;");
89112
}
90113

91-
return q.ToString();
114+
var x = q.ToString();
115+
return x;
92116
}
93117

94118
protected override string GetExcludedColumnName(string columnName)

0 commit comments

Comments
 (0)