diff --git a/src/shared/Z.EF.Plus.BatchDelete.Shared/BatchDelete.cs b/src/shared/Z.EF.Plus.BatchDelete.Shared/BatchDelete.cs index f919788..ef1a0ad 100644 --- a/src/shared/Z.EF.Plus.BatchDelete.Shared/BatchDelete.cs +++ b/src/shared/Z.EF.Plus.BatchDelete.Shared/BatchDelete.cs @@ -380,10 +380,15 @@ internal DbCommand CreateCommand(ObjectQuery query, SchemaEntityType entit // GET command var command = query.Context.CreateStoreCommand(); - bool isMySql = command.GetType().FullName.Contains("MySql"); - var isSqlCe = command.GetType().Name == "SqlCeCommand"; - var isOracle = command.GetType().Namespace.Contains("Oracle"); - var isSQLite = command.GetType().Namespace.Contains("SQLite"); + var commandType = command.GetType(); + var commandFullname = command.GetType().FullName; + var commandNamespace = command.GetType().Namespace; + + var isSqlCe = commandType.Name == "SqlCeCommand"; + var isMySql = commandFullname?.Contains("MySql") ?? false; + var isOracle = commandNamespace?.Contains("Oracle") ?? false; + var isSQLite = commandNamespace?.Contains("SQLite") ?? false; + var isSqlServer = commandFullname == "System.Data.SqlClient.SqlCommand"; // Oracle BindByName if (isOracle) @@ -415,15 +420,21 @@ internal DbCommand CreateCommand(ObjectQuery query, SchemaEntityType entit } else if (isOracle) { - tableName = string.IsNullOrEmpty(store.Schema) || store.Schema == "dbo" ? -string.Concat("\"", store.Table, "\"") : -string.Concat("\"", store.Schema, "\".\"", store.Table, "\""); + tableName = string.IsNullOrEmpty(store.Schema) || store.Schema == "dbo" + ? string.Concat("\"", store.Table, "\"") + : string.Concat("\"", store.Schema, "\".\"", store.Table, "\""); + } + else if (isSqlServer) + { + tableName = string.IsNullOrEmpty(store.Schema) + ? string.Concat("[dbo].[", store.Table, "]") + : string.Concat("[", store.Schema, "].[dbo].[", store.Table, "]"); } else { - tableName = string.IsNullOrEmpty(store.Schema) ? - string.Concat("[", store.Table, "]") : - string.Concat("[", store.Schema, "].[", store.Table, "]"); + tableName = string.IsNullOrEmpty(store.Schema) + ? string.Concat("[", store.Table, "]") + : string.Concat("[", store.Schema, "].[", store.Table, "]"); } // GET keys mappings @@ -451,11 +462,11 @@ internal DbCommand CreateCommand(ObjectQuery query, SchemaEntityType entit CommandTextSqlCeTemplate : isSQLite ? CommandTextSQLiteTemplate : - BatchSize > 0 ? - BatchDelayInterval > 0 ? - CommandTextWhileDelayTemplate : - CommandTextWhileTemplate : - CommandTextTemplate; + BatchSize > 0 ? + BatchDelayInterval > 0 ? + CommandTextWhileDelayTemplate : + CommandTextWhileTemplate : + CommandTextTemplate; // GET inner query var customQuery = query.GetCommandTextAndParameters(); @@ -475,7 +486,15 @@ internal DbCommand CreateCommand(ObjectQuery query, SchemaEntityType entit } else { - primaryKeys = string.Join(Environment.NewLine + "AND ", columnKeys.Select(x => string.Concat("A.", EscapeName(x, isMySql, isOracle), " = B.", EscapeName(x, isMySql, isOracle), ""))); + var columnSynonymsFromSelectClause = ExtractColumnSynonymsFromSelectClause(customQuery.Item1); + if (columnSynonymsFromSelectClause.Any()) //0 + { + primaryKeys = string.Join(Environment.NewLine + " AND ", columnKeys.Select((x, i) => string.Concat("A.", EscapeName(x, isMySql, isOracle), " = B.", EscapeName(columnSynonymsFromSelectClause[i], isMySql, isOracle), ""))); + } + else + { + primaryKeys = string.Join(Environment.NewLine + " AND ", columnKeys.Select(x => string.Concat("A.", EscapeName(x, isMySql, isOracle), " = B.", EscapeName(x, isMySql, isOracle), ""))); + } } // REPLACE template @@ -511,6 +530,15 @@ internal DbCommand CreateCommand(ObjectQuery query, SchemaEntityType entit return command; } + //0 In sqlserver we might have to deal with sqlqueries ala + // + // SELECT + // CAST ([Extent1].[ID_COMPONENT_A] AS bigint) AS [C1], + // CAST ([Extent1].[ID_COMPONENT_B] AS bigint) AS [C2] + // FROM [dbo].[SOME_TABLE] AS [Extent1] ... + // + // we thus need to map the synonyms C1 C2 in the resulting query + #elif EFCORE public DbCommand CreateCommand(IQueryable query, IEntityType entity) { @@ -734,11 +762,24 @@ public DbCommand CreateCommand(IQueryable query, IEntityType entity) return command; } #endif - public string EscapeName(string name, bool isMySql, bool isOracle) + private string EscapeName(string name, bool isMySql, bool isOracle) { return isMySql ? string.Concat("`", name, "`") : isOracle ? string.Concat("\"", name, "\"") : string.Concat("[", name, "]"); } + + private string[] ExtractColumnSynonymsFromSelectClause(string sqlQuery) + { + var firstMatch = SelectClauseInnerTextSpotter.Match(sqlQuery); + if (!firstMatch.Success) + return new string[] { }; + + var selectClauseText = firstMatch.Value.Trim(); + return ParameterSynonymsFromSelectClauseSpotter.Matches(selectClauseText).Cast().Select(x => x.Value).ToArray(); + } + + private static readonly Regex SelectClauseInnerTextSpotter = new Regex(@"(?<=^\s*SELECT\s+).*?(?=\s+FROM)", RegexOptions.IgnoreCase); + private static readonly Regex ParameterSynonymsFromSelectClauseSpotter = new Regex(@"(?<=\s+AS\s+\[)\w+(?=\]\s*(,|$))", RegexOptions.IgnoreCase); } } \ No newline at end of file diff --git a/src/shared/Z.EF.Plus.BatchUpdate.Shared/BatchUpdate.cs b/src/shared/Z.EF.Plus.BatchUpdate.Shared/BatchUpdate.cs index d91af5d..a3b5892 100644 --- a/src/shared/Z.EF.Plus.BatchUpdate.Shared/BatchUpdate.cs +++ b/src/shared/Z.EF.Plus.BatchUpdate.Shared/BatchUpdate.cs @@ -356,11 +356,17 @@ internal DbCommand CreateCommand(ObjectQuery query, SchemaEntityType entit values = values.Except(objectParameters).ToList(); var command = query.Context.CreateStoreCommand(); - bool isMySql = command.GetType().FullName.Contains("MySql"); - var isSqlCe = command.GetType().Name == "SqlCeCommand"; - var isOracle = command.GetType().Namespace.Contains("Oracle"); - var isPostgreSQL = command.GetType().Name == "NpgsqlCommand"; - var isSQLite = command.GetType().Namespace.Contains("SQLite"); + + var commandType = command.GetType(); + var commandFullname = command.GetType().FullName; + var commandNamespace = command.GetType().Namespace; + + var isSqlCe = commandType.Name == "SqlCeCommand"; + var isMySql = commandFullname?.Contains("MySql") ?? false; + var isOracle = commandNamespace?.Contains("Oracle") ?? false; + var isSQLite = commandNamespace?.Contains("SQLite") ?? false; + var isSqlServer = commandFullname == "System.Data.SqlClient.SqlCommand"; + var isPostgreSQL = commandType.Name == "NpgsqlCommand"; // Oracle BindByName if (isOracle) @@ -388,25 +394,31 @@ internal DbCommand CreateCommand(ObjectQuery query, SchemaEntityType entit } else if (isOracle) { - tableName = string.IsNullOrEmpty(store.Schema) || store.Schema == "dbo" ? - string.Concat("\"", store.Table, "\"") : - string.Concat("\"", store.Schema, "\".\"", store.Table, "\""); + tableName = string.IsNullOrEmpty(store.Schema) || store.Schema == "dbo" + ? string.Concat("\"", store.Table, "\"") + : string.Concat("\"", store.Schema, "\".\"", store.Table, "\""); } else if (isPostgreSQL) { - tableName = string.IsNullOrEmpty(store.Schema) ? - string.Concat("\"", store.Table, "\"") : - string.Concat("\"", store.Schema, "\".\"", store.Table, "\""); + tableName = string.IsNullOrEmpty(store.Schema) + ? string.Concat("\"", store.Table, "\"") + : string.Concat("\"", store.Schema, "\".\"", store.Table, "\""); } else if (isSQLite) { tableName = string.Concat("\"", store.Table, "\""); } + else if (isSqlServer) + { + tableName = string.IsNullOrEmpty(store.Schema) + ? string.Concat("[dbo].[", store.Table, "]") + : string.Concat("[", store.Schema, "].[dbo].[", store.Table, "]"); + } else { - tableName = string.IsNullOrEmpty(store.Schema) ? - string.Concat("[", store.Table, "]") : - string.Concat("[", store.Schema, "].[", store.Table, "]"); + tableName = string.IsNullOrEmpty(store.Schema) + ? string.Concat("[", store.Table, "]") + : string.Concat("[", store.Schema, "].[", store.Table, "]"); }