diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlDeleteTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlDeleteTest.cs index 19b06e8ce..1a141a796 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlDeleteTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlDeleteTest.cs @@ -77,13 +77,16 @@ public void ExecuteAffrows() var id = g.mysql.Insert(new Topic { Title = "xxxx" }).ExecuteIdentity(); Assert.Equal(1, delete.Where(a => a.Id == id).ExecuteAffrows()); } + [Fact] public void ExecuteDeleted() { - - //delete.Where(a => a.Id > 0).ExecuteDeleted(); + g.mysql.Insert(new Topic { Clicks = 1, Title = "ExecuteDeleted", CreateTime = DateTime.Now }).ExecuteAffrows(); + var deleted = g.mysql.Delete().Where(m => m.Title == "ExecuteDeleted").ExecuteDeleted(); + Assert.True(deleted.Count > 0); } + [Fact] public void AsTable() { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlInsertTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlInsertTest.cs index 14e91a102..f664831d2 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlInsertTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlInsertTest.cs @@ -123,9 +123,9 @@ public void ExecuteIdentity() public void ExecuteInserted() { var items = new List(); - for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); - - //insert.AppendData(items.First()).ExecuteInserted(); + for (var a = 0; a < 3; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); + var list = g.mysql.Insert(items).ExecuteInserted(); + Assert.True(list.Count == 3); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlUpdateTest.cs index 0f4d8f45c..98ae8016a 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Custom/MySql/Curd/MySqlUpdateTest.cs @@ -301,7 +301,8 @@ public void ExecuteAffrows() [Fact] public void ExecuteUpdated() { - + var list = g.mysql.Update().Set(m => m.Clicks + 1) + .Where(m => m.Id == 1).ExecuteUpdated(); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlDeleteTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlDeleteTest.cs index 2954f27e4..6d24c70f8 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlDeleteTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlDeleteTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -80,8 +80,9 @@ public void ExecuteAffrows() [Fact] public void ExecuteDeleted() { - - //delete.Where(a => a.Id > 0).ExecuteDeleted(); + g.mysql.Insert(new Topic { Clicks = 1, Title = "ExecuteDeleted", CreateTime = DateTime.Now }).ExecuteAffrows(); + var deleted = g.mysql.Delete().Where(m => m.Title == "ExecuteDeleted").ExecuteDeleted(); + Assert.True(deleted.Count > 0); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertTest.cs index 4e10ac87a..d304997ec 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertTest.cs @@ -153,9 +153,9 @@ public void ExecuteIdentity() public void ExecuteInserted() { var items = new List(); - for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); - - //insert.AppendData(items.First()).ExecuteInserted(); + for (var a = 0; a < 3; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); + var list = g.mysql.Insert(items).ExecuteInserted(); + Assert.True(list.Count == 3); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlUpdateTest.cs index 332d157dd..94ec4c177 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlUpdateTest.cs @@ -154,7 +154,7 @@ public void Set() sql = update.Set(a => a.Clicks == a.Clicks * 10 / 1).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); Assert.Equal("UPDATE `tb_topic` SET `Clicks` = `Clicks` * 10 div 1 WHERE (`Id` = 1)", sql); - + var dt2000 = DateTime.Parse("2000-01-01"); sql = update.Set(a => a.Clicks == (a.CreateTime > dt2000 ? 1 : 2)).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); Assert.Equal("UPDATE `tb_topic` SET `Clicks` = case when `CreateTime` > '2000-01-01 00:00:00.000' then 1 else 2 end WHERE (`Id` = 1)", sql); @@ -363,7 +363,8 @@ public void ExecuteAffrows() [Fact] public void ExecuteUpdated() { - + var list = g.mysql.Update().Set(m => m.Clicks + 1) + .Where(m => m.Id == 1).ExecuteUpdated(); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlDeleteTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlDeleteTest.cs index f4b3a11de..8ece0955e 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlDeleteTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlDeleteTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -77,13 +77,16 @@ public void ExecuteAffrows() var id = g.mysql.Insert(new Topic { Title = "xxxx" }).ExecuteIdentity(); Assert.Equal(1, delete.Where(a => a.Id == id).ExecuteAffrows()); } + [Fact] public void ExecuteDeleted() { - - //delete.Where(a => a.Id > 0).ExecuteDeleted(); + g.mysql.Insert(new Topic { Clicks = 1, Title = "ExecuteDeleted", CreateTime = DateTime.Now }).ExecuteAffrows(); + var deleted = g.mysql.Delete().Where(m => m.Title == "ExecuteDeleted").ExecuteDeleted(); + Assert.True(deleted.Count > 0); } + [Fact] public void AsTable() { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlInsertTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlInsertTest.cs index 08cd06adf..cb4e68270 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlInsertTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlInsertTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -123,9 +123,9 @@ public void ExecuteIdentity() public void ExecuteInserted() { var items = new List(); - for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); - - //insert.AppendData(items.First()).ExecuteInserted(); + for (var a = 0; a < 3; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); + var list = g.mysql.Insert(items).ExecuteInserted(); + Assert.True(list.Count == 3); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlUpdateTest.cs index 02d2be2bc..d866ce5d0 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlUpdateTest.cs @@ -301,7 +301,8 @@ public void ExecuteAffrows() [Fact] public void ExecuteUpdated() { - + var list = g.mysql.Update().Set(m => m.Clicks + 1) + .Where(m => m.Id == 1).ExecuteUpdated(); } [Fact] diff --git a/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlDelete.cs b/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlDelete.cs index 6645c100c..ba45c4885 100644 --- a/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlDelete.cs +++ b/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlDelete.cs @@ -23,31 +23,44 @@ public override List ExecuteDeleted() { var ret = new List(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; ToSqlFetch(sb => { if (dbParms == null) { dbParms = _params.ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in _table.Columns.Values) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + var deleteSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, deleteSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + // 必须在 DELETE 之前 SELECT,否则数据已被删除无法查询 + var whereIdx = deleteSql.LastIndexOf(" WHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(deleteSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms)); + } + _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, deleteSql, _commandTimeout, dbParms); } catch (Exception ex) { @@ -63,7 +76,7 @@ public override List ExecuteDeleted() if (dbParms != null) { this.ClearData(); - sbret.Clear(); + sbSelectCols?.Clear(); } return ret; } @@ -74,31 +87,44 @@ async public override Task> ExecuteDeletedAsync(CancellationToken cance { var ret = new List(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; await ToSqlFetchAsync(async sb => { if (dbParms == null) { dbParms = _params.ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in _table.Columns.Values) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + var deleteSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, deleteSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + // 必须在 DELETE 之前 SELECT,否则数据已被删除无法查询 + var whereIdx = deleteSql.LastIndexOf(" WHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(deleteSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms, cancellationToken)); + } + await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, deleteSql, _commandTimeout, dbParms, cancellationToken); } catch (Exception ex) { @@ -114,7 +140,7 @@ await ToSqlFetchAsync(async sb => if (dbParms != null) { this.ClearData(); - sbret.Clear(); + sbSelectCols?.Clear(); } return ret; } diff --git a/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlInsert.cs b/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlInsert.cs index 505ada97c..71bc66cfe 100644 --- a/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlInsert.cs +++ b/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlInsert.cs @@ -87,24 +87,74 @@ protected override List RawExecuteInserted() var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return new List(); - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); Exception exception = null; try { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, _params); + var affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params); + + if (affrows > 0) + { + var pk = _table.Primarys.FirstOrDefault(); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + + var sbSelect = new StringBuilder(); + sbSelect.Append("SELECT "); + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))) + .Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + sbSelect.Append(" FROM ").Append(tableName); + + if (pk != null && pk.Attribute.IsIdentity && _insertIdentity == false) + { + var lastIdObj = _orm.Ado.ExecuteScalar(_connection, _transaction, CommandType.Text, + "SELECT LAST_INSERT_ID();", _commandTimeout, null); + if (lastIdObj != null && lastIdObj != DBNull.Value) + { + var lastId = Convert.ToInt64(lastIdObj); + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" >= ").Append(lastId) + .Append(" ORDER BY ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" LIMIT ").Append(affrows); + } + else + { + return ret; + } + } + else if (pk != null && _source.Any()) + { + var pkValues = _source.Select(a => pk.GetDbValue(a)).Distinct().ToArray(); + if (pkValues.Length == 0) return ret; + + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" IN ("); + for (var i = 0; i < pkValues.Length; i++) + { + if (i > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.FormatSql("{0}", pkValues[i])); + } + sbSelect.Append(")"); + } + else + { + return ret; + } + + var selectSql = sbSelect.ToString(); + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, selectSql, null); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, + CommandType.Text, selectSql, _commandTimeout, null); + } } catch (Exception ex) { @@ -167,24 +217,74 @@ async protected override Task> RawExecuteInsertedAsync(CancellationToke var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return new List(); - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); Exception exception = null; try { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, _params, cancellationToken); + var affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params, cancellationToken); + + if (affrows > 0) + { + var pk = _table.Primarys.FirstOrDefault(); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + + var sbSelect = new StringBuilder(); + sbSelect.Append("SELECT "); + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))) + .Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + sbSelect.Append(" FROM ").Append(tableName); + + if (pk != null && pk.Attribute.IsIdentity && _insertIdentity == false) + { + var lastIdObj = await _orm.Ado.ExecuteScalarAsync(_connection, _transaction, CommandType.Text, + "SELECT LAST_INSERT_ID();", _commandTimeout, null, cancellationToken); + if (lastIdObj != null && lastIdObj != DBNull.Value) + { + var lastId = Convert.ToInt64(lastIdObj); + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" >= ").Append(lastId) + .Append(" ORDER BY ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" LIMIT ").Append(affrows); + } + else + { + return ret; + } + } + else if (pk != null && _source.Any()) + { + var pkValues = _source.Select(a => pk.GetDbValue(a)).Distinct().ToArray(); + if (pkValues.Length == 0) return ret; + + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" IN ("); + for (var i = 0; i < pkValues.Length; i++) + { + if (i > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.FormatSql("{0}", pkValues[i])); + } + sbSelect.Append(")"); + } + else + { + return ret; + } + + var selectSql = sbSelect.ToString(); + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, selectSql, null); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, + CommandType.Text, selectSql, _commandTimeout, null, cancellationToken); + } } catch (Exception ex) { diff --git a/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlUpdate.cs b/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlUpdate.cs index 53e436521..df25d8e3e 100644 --- a/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlUpdate.cs +++ b/Providers/FreeSql.Provider.Custom/MySql/Curd/CustomMySqlUpdate.cs @@ -35,34 +35,50 @@ protected override List RawExecuteUpdated(IEnumerable(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; ToSqlFetch(sb => { if (dbParms == null) { dbParms = _params.Concat(_paramsSource).ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in columns) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + var updateSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, updateSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; - var rettmp = _orm.Ado.Query(queryType, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(rettmp.Count, sql, dbParms); - ret.AddRange(rettmp); + var affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, updateSql, _commandTimeout, dbParms); + ValidateVersionAndThrow(affrows, updateSql, dbParms); + + if (affrows > 0) + { + var whereIdx = updateSql.LastIndexOf(" \r\nWHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(updateSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; + var rettmp = _orm.Ado.Query(queryType, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms); + ret.AddRange(rettmp); + } + } } catch (Exception ex) { @@ -75,7 +91,7 @@ protected override List RawExecuteUpdated(IEnumerable> RawExecuteUpdatedAsync(IEn { var ret = new List(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; await ToSqlFetchAsync(async sb => { if (dbParms == null) { dbParms = _params.Concat(_paramsSource).ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in columns) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + var updateSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, updateSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; - var rettmp = await _orm.Ado.QueryAsync(queryType, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(rettmp.Count, sql, dbParms); - ret.AddRange(rettmp); + var affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, updateSql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(affrows, updateSql, dbParms); + + if (affrows > 0) + { + var whereIdx = updateSql.LastIndexOf(" \r\nWHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(updateSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; + var rettmp = await _orm.Ado.QueryAsync(queryType, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms, cancellationToken); + ret.AddRange(rettmp); + } + } } catch (Exception ex) { @@ -165,7 +197,7 @@ await ToSqlFetchAsync(async sb => _orm.Aop.CurdAfterHandler?.Invoke(this, after); } }); - sbret?.Clear(); + sbSelectCols?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.MySql/Curd/MySqlDelete.cs b/Providers/FreeSql.Provider.MySql/Curd/MySqlDelete.cs index 5d38e44a8..b963d7615 100644 --- a/Providers/FreeSql.Provider.MySql/Curd/MySqlDelete.cs +++ b/Providers/FreeSql.Provider.MySql/Curd/MySqlDelete.cs @@ -23,31 +23,44 @@ public override List ExecuteDeleted() { var ret = new List(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; ToSqlFetch(sb => { if (dbParms == null) { dbParms = _params.ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in _table.Columns.Values) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + var deleteSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, deleteSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + // 必须在 DELETE 之前 SELECT,否则数据已被删除无法查询 + var whereIdx = deleteSql.LastIndexOf(" WHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(deleteSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms)); + } + _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, deleteSql, _commandTimeout, dbParms); } catch (Exception ex) { @@ -63,7 +76,7 @@ public override List ExecuteDeleted() if (dbParms != null) { this.ClearData(); - sbret.Clear(); + sbSelectCols?.Clear(); } return ret; } @@ -74,31 +87,44 @@ async public override Task> ExecuteDeletedAsync(CancellationToken cance { var ret = new List(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; await ToSqlFetchAsync(async sb => { if (dbParms == null) { dbParms = _params.ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in _table.Columns.Values) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + var deleteSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, deleteSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + // 必须在 DELETE 之前 SELECT,否则数据已被删除无法查询 + var whereIdx = deleteSql.LastIndexOf(" WHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(deleteSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms, cancellationToken)); + } + await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, deleteSql, _commandTimeout, dbParms, cancellationToken); } catch (Exception ex) { @@ -114,7 +140,7 @@ await ToSqlFetchAsync(async sb => if (dbParms != null) { this.ClearData(); - sbret.Clear(); + sbSelectCols?.Clear(); } return ret; } diff --git a/Providers/FreeSql.Provider.MySql/Curd/MySqlInsert.cs b/Providers/FreeSql.Provider.MySql/Curd/MySqlInsert.cs index 82e44fe09..94b0f1a40 100644 --- a/Providers/FreeSql.Provider.MySql/Curd/MySqlInsert.cs +++ b/Providers/FreeSql.Provider.MySql/Curd/MySqlInsert.cs @@ -75,24 +75,74 @@ protected override List RawExecuteInserted() var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return new List(); - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); Exception exception = null; try { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, _params); + var affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params); + + if (affrows > 0) + { + var pk = _table.Primarys.FirstOrDefault(); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + + var sbSelect = new StringBuilder(); + sbSelect.Append("SELECT "); + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))) + .Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + sbSelect.Append(" FROM ").Append(tableName); + + if (pk != null && pk.Attribute.IsIdentity && _insertIdentity == false) + { + var lastIdObj = _orm.Ado.ExecuteScalar(_connection, _transaction, CommandType.Text, + "SELECT LAST_INSERT_ID();", _commandTimeout, null); + if (lastIdObj != null && lastIdObj != DBNull.Value) + { + var lastId = Convert.ToInt64(lastIdObj); + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" >= ").Append(lastId) + .Append(" ORDER BY ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" LIMIT ").Append(affrows); + } + else + { + return ret; + } + } + else if (pk != null && _source.Any()) + { + var pkValues = _source.Select(a => pk.GetDbValue(a)).Distinct().ToArray(); + if (pkValues.Length == 0) return ret; + + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" IN ("); + for (var i = 0; i < pkValues.Length; i++) + { + if (i > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.FormatSql("{0}", pkValues[i])); + } + sbSelect.Append(")"); + } + else + { + return ret; + } + + var selectSql = sbSelect.ToString(); + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, selectSql, null); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, + CommandType.Text, selectSql, _commandTimeout, null); + } } catch (Exception ex) { @@ -144,24 +194,74 @@ async protected override Task> RawExecuteInsertedAsync(CancellationToke var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return new List(); - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); Exception exception = null; try { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, _params, cancellationToken); + var affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params, cancellationToken); + + if (affrows > 0) + { + var pk = _table.Primarys.FirstOrDefault(); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + + var sbSelect = new StringBuilder(); + sbSelect.Append("SELECT "); + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))) + .Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + sbSelect.Append(" FROM ").Append(tableName); + + if (pk != null && pk.Attribute.IsIdentity && _insertIdentity == false) + { + var lastIdObj = await _orm.Ado.ExecuteScalarAsync(_connection, _transaction, CommandType.Text, + "SELECT LAST_INSERT_ID();", _commandTimeout, null, cancellationToken); + if (lastIdObj != null && lastIdObj != DBNull.Value) + { + var lastId = Convert.ToInt64(lastIdObj); + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" >= ").Append(lastId) + .Append(" ORDER BY ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" LIMIT ").Append(affrows); + } + else + { + return ret; + } + } + else if (pk != null && _source.Any()) + { + var pkValues = _source.Select(a => pk.GetDbValue(a)).Distinct().ToArray(); + if (pkValues.Length == 0) return ret; + + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" IN ("); + for (var i = 0; i < pkValues.Length; i++) + { + if (i > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.FormatSql("{0}", pkValues[i])); + } + sbSelect.Append(")"); + } + else + { + return ret; + } + + var selectSql = sbSelect.ToString(); + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, selectSql, null); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, + CommandType.Text, selectSql, _commandTimeout, null, cancellationToken); + } } catch (Exception ex) { diff --git a/Providers/FreeSql.Provider.MySql/Curd/MySqlUpdate.cs b/Providers/FreeSql.Provider.MySql/Curd/MySqlUpdate.cs index bccb59111..951389348 100644 --- a/Providers/FreeSql.Provider.MySql/Curd/MySqlUpdate.cs +++ b/Providers/FreeSql.Provider.MySql/Curd/MySqlUpdate.cs @@ -35,34 +35,50 @@ protected override List RawExecuteUpdated(IEnumerable(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; ToSqlFetch(sb => { if (dbParms == null) { dbParms = _params.Concat(_paramsSource).ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in columns) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + var updateSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, updateSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; - var rettmp = _orm.Ado.Query(queryType, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(rettmp.Count, sql, dbParms); - ret.AddRange(rettmp); + var affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, updateSql, _commandTimeout, dbParms); + ValidateVersionAndThrow(affrows, updateSql, dbParms); + + if (affrows > 0) + { + var whereIdx = updateSql.LastIndexOf(" \r\nWHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(updateSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; + var rettmp = _orm.Ado.Query(queryType, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms); + ret.AddRange(rettmp); + } + } } catch (Exception ex) { @@ -75,7 +91,7 @@ protected override List RawExecuteUpdated(IEnumerable> RawExecuteUpdatedAsync(IEn { var ret = new List(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; await ToSqlFetchAsync(async sb => { if (dbParms == null) { dbParms = _params.Concat(_paramsSource).ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in columns) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + var updateSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, updateSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; - var rettmp = await _orm.Ado.QueryAsync(queryType, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(rettmp.Count, sql, dbParms); - ret.AddRange(rettmp); + var affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, updateSql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(affrows, updateSql, dbParms); + + if (affrows > 0) + { + var whereIdx = updateSql.LastIndexOf(" \r\nWHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(updateSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; + var rettmp = await _orm.Ado.QueryAsync(queryType, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms, cancellationToken); + ret.AddRange(rettmp); + } + } } catch (Exception ex) { @@ -165,7 +197,7 @@ await ToSqlFetchAsync(async sb => _orm.Aop.CurdAfterHandler?.Invoke(this, after); } }); - sbret?.Clear(); + sbSelectCols?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlDelete.cs b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlDelete.cs index 24aa2168e..153ae043c 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlDelete.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlDelete.cs @@ -23,31 +23,44 @@ public override List ExecuteDeleted() { var ret = new List(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; ToSqlFetch(sb => { if (dbParms == null) { dbParms = _params.ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in _table.Columns.Values) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + var deleteSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, deleteSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + // 必须在 DELETE 之前 SELECT,否则数据已被删除无法查询 + var whereIdx = deleteSql.LastIndexOf(" WHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(deleteSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms)); + } + _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, deleteSql, _commandTimeout, dbParms); } catch (Exception ex) { @@ -63,7 +76,7 @@ public override List ExecuteDeleted() if (dbParms != null) { this.ClearData(); - sbret.Clear(); + sbSelectCols?.Clear(); } return ret; } @@ -74,31 +87,44 @@ async public override Task> ExecuteDeletedAsync(CancellationToken cance { var ret = new List(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; await ToSqlFetchAsync(async sb => { if (dbParms == null) { dbParms = _params.ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in _table.Columns.Values) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + var deleteSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, deleteSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + // 必须在 DELETE 之前 SELECT,否则数据已被删除无法查询 + var whereIdx = deleteSql.LastIndexOf(" WHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(deleteSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms, cancellationToken)); + } + await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, deleteSql, _commandTimeout, dbParms, cancellationToken); } catch (Exception ex) { @@ -114,7 +140,7 @@ await ToSqlFetchAsync(async sb => if (dbParms != null) { this.ClearData(); - sbret.Clear(); + sbSelectCols?.Clear(); } return ret; } diff --git a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsert.cs b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsert.cs index 25adfbe3b..e19c04529 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsert.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsert.cs @@ -87,24 +87,74 @@ protected override List RawExecuteInserted() var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return new List(); - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); Exception exception = null; try { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, _params); + var affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params); + + if (affrows > 0) + { + var pk = _table.Primarys.FirstOrDefault(); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + + var sbSelect = new StringBuilder(); + sbSelect.Append("SELECT "); + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))) + .Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + sbSelect.Append(" FROM ").Append(tableName); + + if (pk != null && pk.Attribute.IsIdentity && _insertIdentity == false) + { + var lastIdObj = _orm.Ado.ExecuteScalar(_connection, _transaction, CommandType.Text, + "SELECT LAST_INSERT_ID();", _commandTimeout, null); + if (lastIdObj != null && lastIdObj != DBNull.Value) + { + var lastId = Convert.ToInt64(lastIdObj); + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" >= ").Append(lastId) + .Append(" ORDER BY ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" LIMIT ").Append(affrows); + } + else + { + return ret; + } + } + else if (pk != null && _source.Any()) + { + var pkValues = _source.Select(a => pk.GetDbValue(a)).Distinct().ToArray(); + if (pkValues.Length == 0) return ret; + + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" IN ("); + for (var i = 0; i < pkValues.Length; i++) + { + if (i > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.FormatSql("{0}", pkValues[i])); + } + sbSelect.Append(")"); + } + else + { + return ret; + } + + var selectSql = sbSelect.ToString(); + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, selectSql, null); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, + CommandType.Text, selectSql, _commandTimeout, null); + } } catch (Exception ex) { @@ -167,24 +217,74 @@ async protected override Task> RawExecuteInsertedAsync(CancellationToke var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return new List(); - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); Exception exception = null; try { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, _params, cancellationToken); + var affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params, cancellationToken); + + if (affrows > 0) + { + var pk = _table.Primarys.FirstOrDefault(); + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + + var sbSelect = new StringBuilder(); + sbSelect.Append("SELECT "); + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))) + .Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + sbSelect.Append(" FROM ").Append(tableName); + + if (pk != null && pk.Attribute.IsIdentity && _insertIdentity == false) + { + var lastIdObj = await _orm.Ado.ExecuteScalarAsync(_connection, _transaction, CommandType.Text, + "SELECT LAST_INSERT_ID();", _commandTimeout, null, cancellationToken); + if (lastIdObj != null && lastIdObj != DBNull.Value) + { + var lastId = Convert.ToInt64(lastIdObj); + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" >= ").Append(lastId) + .Append(" ORDER BY ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" LIMIT ").Append(affrows); + } + else + { + return ret; + } + } + else if (pk != null && _source.Any()) + { + var pkValues = _source.Select(a => pk.GetDbValue(a)).Distinct().ToArray(); + if (pkValues.Length == 0) return ret; + + sbSelect.Append(" WHERE ").Append(_commonUtils.QuoteSqlName(pk.Attribute.Name)) + .Append(" IN ("); + for (var i = 0; i < pkValues.Length; i++) + { + if (i > 0) sbSelect.Append(", "); + sbSelect.Append(_commonUtils.FormatSql("{0}", pkValues[i])); + } + sbSelect.Append(")"); + } + else + { + return ret; + } + + var selectSql = sbSelect.ToString(); + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, selectSql, null); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, + CommandType.Text, selectSql, _commandTimeout, null, cancellationToken); + } } catch (Exception ex) { diff --git a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlUpdate.cs b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlUpdate.cs index 058a05764..09094e478 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlUpdate.cs @@ -35,34 +35,50 @@ protected override List RawExecuteUpdated(IEnumerable(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; ToSqlFetch(sb => { if (dbParms == null) { dbParms = _params.Concat(_paramsSource).ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in columns) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + var updateSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, updateSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; - var rettmp = _orm.Ado.Query(queryType, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(rettmp.Count, sql, dbParms); - ret.AddRange(rettmp); + var affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, updateSql, _commandTimeout, dbParms); + ValidateVersionAndThrow(affrows, updateSql, dbParms); + + if (affrows > 0) + { + var whereIdx = updateSql.LastIndexOf(" \r\nWHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(updateSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; + var rettmp = _orm.Ado.Query(queryType, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms); + ret.AddRange(rettmp); + } + } } catch (Exception ex) { @@ -75,7 +91,7 @@ protected override List RawExecuteUpdated(IEnumerable> RawExecuteUpdatedAsync(IEn { var ret = new List(); DbParameter[] dbParms = null; - StringBuilder sbret = null; + StringBuilder sbSelectCols = null; await ToSqlFetchAsync(async sb => { if (dbParms == null) { dbParms = _params.Concat(_paramsSource).ToArray(); - sbret = new StringBuilder(); - sbret.Append(" RETURNING "); - + sbSelectCols = new StringBuilder(); var colidx = 0; foreach (var col in columns) { - if (colidx > 0) sbret.Append(", "); - sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + if (colidx > 0) sbSelectCols.Append(", "); + sbSelectCols.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); ++colidx; } } - var sql = sb.Append(sbret).ToString(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + var updateSql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, updateSql, dbParms); _orm.Aop.CurdBeforeHandler?.Invoke(this, before); Exception exception = null; try { - var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; - var rettmp = await _orm.Ado.QueryAsync(queryType, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(rettmp.Count, sql, dbParms); - ret.AddRange(rettmp); + var affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, updateSql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(affrows, updateSql, dbParms); + + if (affrows > 0) + { + var whereIdx = updateSql.LastIndexOf(" \r\nWHERE "); + if (whereIdx >= 0) + { + var tableName = _commonUtils.QuoteSqlName(TableRuleInvoke()); + var selectSql = new StringBuilder() + .Append("SELECT ").Append(sbSelectCols) + .Append(" FROM ").Append(tableName).Append(updateSql.Substring(whereIdx)) + .ToString(); + + var before2 = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, selectSql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before2); + + var queryType = typeof(TReturn) == typeof(T1) ? (_table.TypeLazy ?? _table.Type) : null; + var rettmp = await _orm.Ado.QueryAsync(queryType, _connection, _transaction, CommandType.Text, selectSql, _commandTimeout, dbParms, cancellationToken); + ret.AddRange(rettmp); + } + } } catch (Exception ex) { @@ -165,7 +197,7 @@ await ToSqlFetchAsync(async sb => _orm.Aop.CurdAfterHandler?.Invoke(this, after); } }); - sbret?.Clear(); + sbSelectCols?.Clear(); return ret; } #endif