mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-12-30 19:25:49 +08:00
- 增加 [Table(AsTable = xx)] 分表特性,完成分表插入/删除;
This commit is contained in:
@@ -95,7 +95,9 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
if (objects == null) return;
|
||||
var syncObjects = objects.Where(a => a.entityType != null && a.entityType != typeof(object) && _dicSycedGetOrAdd(a.entityType).ContainsKey(GetTableNameLowerOrUpper(a.tableName)) == false && GetTableByEntity(a.entityType)?.DisableSyncStructure == false)
|
||||
.Select(a => new TypeAndName(a.entityType, GetTableNameLowerOrUpper(a.tableName))).ToArray();
|
||||
.Select(a => new TypeAndName(a.entityType, GetTableNameLowerOrUpper(a.tableName)))
|
||||
.Where(a => !(string.IsNullOrEmpty(a.tableName) == true && GetTableByEntity(a.entityType)?.AsTableImpl != null))
|
||||
.ToArray();
|
||||
if (syncObjects.Any() == false) return;
|
||||
var before = new Aop.SyncStructureBeforeEventArgs(syncObjects.Select(a => a.entityType).ToArray());
|
||||
_orm.Aop.SyncStructureBeforeHandler?.Invoke(this, before);
|
||||
|
||||
@@ -10,8 +10,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
|
||||
public abstract partial class DeleteProvider<T1> : IDelete<T1>
|
||||
public abstract partial class DeleteProvider
|
||||
{
|
||||
public IFreeSql _orm;
|
||||
public CommonUtils _commonUtils;
|
||||
@@ -26,7 +25,10 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public DbConnection _connection;
|
||||
public int _commandTimeout = 0;
|
||||
public Action<StringBuilder> _interceptSql;
|
||||
}
|
||||
|
||||
public abstract partial class DeleteProvider<T1> : DeleteProvider, IDelete<T1>
|
||||
{
|
||||
public DeleteProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
|
||||
{
|
||||
_orm = orm;
|
||||
@@ -66,28 +68,32 @@ namespace FreeSql.Internal.CommonProvider
|
||||
|
||||
public int ExecuteAffrows()
|
||||
{
|
||||
var sql = this.ToSql();
|
||||
if (string.IsNullOrEmpty(sql)) return 0;
|
||||
var dbParms = _params.ToArray();
|
||||
var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms);
|
||||
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
|
||||
var affrows = 0;
|
||||
Exception exception = null;
|
||||
try
|
||||
DbParameter[] dbParms = null;
|
||||
ToSqlFetch(sb =>
|
||||
{
|
||||
affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
|
||||
_orm.Aop.CurdAfterHandler?.Invoke(this, after);
|
||||
}
|
||||
this.ClearData();
|
||||
if (dbParms == null) dbParms = _params.ToArray();
|
||||
var sql = sb.ToString();
|
||||
var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms);
|
||||
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
|
||||
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
affrows += _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
|
||||
_orm.Aop.CurdAfterHandler?.Invoke(this, after);
|
||||
}
|
||||
});
|
||||
if (dbParms != null) this.ClearData();
|
||||
return affrows;
|
||||
}
|
||||
public abstract List<T1> ExecuteDeleted();
|
||||
@@ -165,16 +171,77 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public virtual string ToSql()
|
||||
{
|
||||
if (_whereTimes <= 0) return null;
|
||||
var sb = new StringBuilder().Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" WHERE ").Append(_where);
|
||||
var sb = new StringBuilder();
|
||||
ToSqlFetch(sql =>
|
||||
{
|
||||
sb.Append(sql).Append("\r\n\r\n;\r\n\r\n");
|
||||
});
|
||||
if (sb.Length > 0) sb.Remove(sb.Length - 9, 9);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void ToSqlFetch(Action<StringBuilder> fetch)
|
||||
{
|
||||
if (_whereTimes <= 0) return;
|
||||
var newwhere = new StringBuilder().Append(" WHERE ").Append(_where);
|
||||
|
||||
if (_whereGlobalFilter.Any())
|
||||
{
|
||||
var globalFilterCondi = _commonExpression.GetWhereCascadeSql(new SelectTableInfo { Table = _table }, _whereGlobalFilter, false);
|
||||
if (string.IsNullOrEmpty(globalFilterCondi) == false)
|
||||
sb.Append(" AND ").Append(globalFilterCondi);
|
||||
newwhere.Append(" AND ").Append(globalFilterCondi);
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
if (_table.AsTableImpl != null)
|
||||
{
|
||||
var names = _table.AsTableImpl.GetTableNamesBySqlWhere(newwhere.ToString(), _params, _table, _commonUtils);
|
||||
foreach (var name in names)
|
||||
{
|
||||
_tableRule = old => name;
|
||||
sb.Clear().Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(newwhere);
|
||||
_interceptSql?.Invoke(sb);
|
||||
fetch(sb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sb.Insert(0, _commonUtils.QuoteSqlName(TableRuleInvoke())).Insert(0, "DELETE FROM ");
|
||||
_interceptSql?.Invoke(sb);
|
||||
return sb.ToString();
|
||||
fetch(sb);
|
||||
}
|
||||
#if net40
|
||||
#else
|
||||
async public Task ToSqlFetchAsync(Func<StringBuilder, Task> fetchAsync)
|
||||
{
|
||||
if (_whereTimes <= 0) return;
|
||||
var newwhere = new StringBuilder().Append(" WHERE ").Append(_where);
|
||||
|
||||
if (_whereGlobalFilter.Any())
|
||||
{
|
||||
var globalFilterCondi = _commonExpression.GetWhereCascadeSql(new SelectTableInfo { Table = _table }, _whereGlobalFilter, false);
|
||||
if (string.IsNullOrEmpty(globalFilterCondi) == false)
|
||||
newwhere.Append(" AND ").Append(globalFilterCondi);
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
if (_table.AsTableImpl != null)
|
||||
{
|
||||
var names = _table.AsTableImpl.GetTableNamesBySqlWhere(newwhere.ToString(), _params, _table, _commonUtils);
|
||||
foreach (var name in names)
|
||||
{
|
||||
_tableRule = old => name;
|
||||
sb.Clear().Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(newwhere);
|
||||
_interceptSql?.Invoke(sb);
|
||||
await fetchAsync(sb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sb.Insert(0, _commonUtils.QuoteSqlName(TableRuleInvoke())).Insert(0, "DELETE FROM ");
|
||||
_interceptSql?.Invoke(sb);
|
||||
await fetchAsync(sb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,28 +16,32 @@ namespace FreeSql.Internal.CommonProvider
|
||||
#else
|
||||
async public Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var sql = this.ToSql();
|
||||
if (string.IsNullOrEmpty(sql)) return 0;
|
||||
var dbParms = _params.ToArray();
|
||||
var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms);
|
||||
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
|
||||
var affrows = 0;
|
||||
Exception exception = null;
|
||||
try
|
||||
DbParameter[] dbParms = null;
|
||||
await ToSqlFetchAsync(async sb =>
|
||||
{
|
||||
affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
|
||||
_orm.Aop.CurdAfterHandler?.Invoke(this, after);
|
||||
}
|
||||
this.ClearData();
|
||||
if (dbParms == null) dbParms = _params.ToArray();
|
||||
var sql = sb.ToString();
|
||||
var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms);
|
||||
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
|
||||
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
affrows += await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
|
||||
_orm.Aop.CurdAfterHandler?.Invoke(this, after);
|
||||
}
|
||||
});
|
||||
if (dbParms != null) this.ClearData();
|
||||
return affrows;
|
||||
}
|
||||
public abstract Task<List<T1>> ExecuteDeletedAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
@@ -14,12 +14,11 @@ using System.Collections;
|
||||
namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
|
||||
public abstract partial class InsertProvider<T1> : IInsert<T1> where T1 : class
|
||||
public abstract partial class InsertProvider
|
||||
{
|
||||
public IFreeSql _orm;
|
||||
public CommonUtils _commonUtils;
|
||||
public CommonExpression _commonExpression;
|
||||
public List<T1> _source = new List<T1>();
|
||||
public Dictionary<string, bool> _ignore = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
|
||||
public Dictionary<string, bool> _auditValueChangedDict = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
|
||||
public TableInfo _table;
|
||||
@@ -28,11 +27,17 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public bool _noneParameter, _insertIdentity;
|
||||
public int _batchValuesLimit, _batchParameterLimit;
|
||||
public bool _batchAutoTransaction = true;
|
||||
public Action<BatchProgressStatus<T1>> _batchProgress;
|
||||
public DbParameter[] _params;
|
||||
public DbTransaction _transaction;
|
||||
public DbConnection _connection;
|
||||
public int _commandTimeout = 0;
|
||||
}
|
||||
|
||||
public abstract partial class InsertProvider<T1> : InsertProvider, IInsert<T1> where T1 : class
|
||||
{
|
||||
public List<T1> _source = new List<T1>();
|
||||
internal List<T1> _sourceOld;
|
||||
public Action<BatchProgressStatus<T1>> _batchProgress;
|
||||
|
||||
public InsertProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
|
||||
{
|
||||
@@ -43,6 +48,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_noneParameter = _orm.CodeFirst.IsNoneCommandParameter;
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
|
||||
IgnoreCanInsert();
|
||||
_sourceOld = _source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -62,6 +68,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_batchProgress = null;
|
||||
_insertIdentity = false;
|
||||
_source.Clear();
|
||||
_sourceOld = _source;
|
||||
_ignore.Clear();
|
||||
_auditValueChangedDict.Clear();
|
||||
_params = null;
|
||||
@@ -189,7 +196,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
|
||||
#region 参数化数据限制,或values数量限制
|
||||
protected List<T1>[] SplitSource(int valuesLimit, int parameterLimit)
|
||||
protected List<T1>[] SplitSource(int valuesLimit, int parameterLimit, bool isAsTableSplited = false)
|
||||
{
|
||||
valuesLimit = valuesLimit - 1;
|
||||
parameterLimit = parameterLimit - 1;
|
||||
@@ -198,6 +205,28 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (_source == null || _source.Any() == false) return new List<T1>[0];
|
||||
if (_source.Count == 1) return new[] { _source };
|
||||
|
||||
if (_table.AsTableImpl != null && isAsTableSplited == false)
|
||||
{
|
||||
var atarr = _source.Select(a => new
|
||||
{
|
||||
item = a,
|
||||
splitKey = _table.AsTableImpl.GetTableNameByColumnValue(_table.AsTableColumn.GetValue(a), true)
|
||||
}).GroupBy(a => a.splitKey, a => a.item).ToArray();
|
||||
if (atarr.Length > 1)
|
||||
{
|
||||
var oldSource = _source;
|
||||
var arrret = new List<List<T1>>();
|
||||
foreach (var item in atarr)
|
||||
{
|
||||
_source = item.ToList();
|
||||
var itemret = SplitSource(valuesLimit + 1, parameterLimit + 1, true);
|
||||
arrret.AddRange(itemret);
|
||||
}
|
||||
_source = oldSource;
|
||||
return arrret.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
var takeMax = valuesLimit;
|
||||
if (_noneParameter == false)
|
||||
{
|
||||
@@ -510,8 +539,8 @@ namespace FreeSql.Internal.CommonProvider
|
||||
protected string TableRuleInvoke()
|
||||
{
|
||||
var tbname = _table?.DbName ?? "";
|
||||
if (_tableRule == null) return tbname;
|
||||
var newname = _tableRule(tbname);
|
||||
if (_tableRule == null && _table.AsTableImpl == null) return tbname;
|
||||
var newname = _table.AsTableImpl?.GetTableNameByColumnValue(_source.Any() ? _table.AsTableColumn.GetValue(_source.FirstOrDefault()) : DateTime.Now) ?? _tableRule(tbname);
|
||||
if (newname == tbname) return tbname;
|
||||
if (string.IsNullOrEmpty(newname)) return tbname;
|
||||
if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower();
|
||||
@@ -540,14 +569,38 @@ namespace FreeSql.Internal.CommonProvider
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual string ToSql() => ToSqlValuesOrSelectUnionAllExtension102(true, null, null);
|
||||
public virtual string ToSql() => ToSqlValuesOrSelectUnionAllExtension103(true, null, null, false);
|
||||
|
||||
public string ToSqlValuesOrSelectUnionAll(bool isValues = true) => ToSqlValuesOrSelectUnionAllExtension102(isValues, null, null);
|
||||
public string ToSqlValuesOrSelectUnionAllExtension101(bool isValues, Action<object, int, StringBuilder> onrow) => ToSqlValuesOrSelectUnionAllExtension102(isValues, null, onrow);
|
||||
public string ToSqlValuesOrSelectUnionAllExtension102(bool isValues, Action<object, int, StringBuilder> onrowPre, Action<object, int, StringBuilder> onrow)
|
||||
public string ToSqlValuesOrSelectUnionAll(bool isValues = true) => ToSqlValuesOrSelectUnionAllExtension103(isValues, null, null, false);
|
||||
public string ToSqlValuesOrSelectUnionAllExtension101(bool isValues, Action<object, int, StringBuilder> onrow) => ToSqlValuesOrSelectUnionAllExtension103(isValues, null, onrow, false);
|
||||
public string ToSqlValuesOrSelectUnionAllExtension102(bool isValues, Action<object, int, StringBuilder> onrowPre, Action<object, int, StringBuilder> onrow) => ToSqlValuesOrSelectUnionAllExtension103(isValues, null, onrow, false);
|
||||
string ToSqlValuesOrSelectUnionAllExtension103(bool isValues, Action<object, int, StringBuilder> onrowPre, Action<object, int, StringBuilder> onrow, bool isAsTableSplited)
|
||||
{
|
||||
if (_source == null || _source.Any() == false) return null;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (_table.AsTableImpl != null && isAsTableSplited == false && _source == _sourceOld)
|
||||
{
|
||||
var atarr = _source.Select(a => new
|
||||
{
|
||||
item = a,
|
||||
splitKey = _table.AsTableImpl.GetTableNameByColumnValue(_table.AsTableColumn.GetValue(a), true)
|
||||
}).GroupBy(a => a.splitKey, a => a.item).ToArray();
|
||||
if (atarr.Length > 1)
|
||||
{
|
||||
var oldSource = _source;
|
||||
var arrret = new List<List<T1>>();
|
||||
foreach (var item in atarr)
|
||||
{
|
||||
_source = item.ToList();
|
||||
sb.Append(ToSqlValuesOrSelectUnionAllExtension103(isValues, onrowPre, onrow, true)).Append("\r\n\r\n;\r\n\r\n");
|
||||
}
|
||||
_source = oldSource;
|
||||
if (sb.Length > 0) sb.Remove(sb.Length - 9, 9);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append("INSERT INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append('(');
|
||||
var colidx = 0;
|
||||
foreach (var col in _table.Columns.Values)
|
||||
|
||||
Reference in New Issue
Block a user