- 增加 ISelect.ToDataTable 系列方法;

- 增加 无参数化命令执行,可配置全局 ICodeFirst.IsNoneCommandParameter、或临时 IInsert/IUpdate.NoneParameter() 便于调试;
- 关闭 自动同步结构功能,避免线上环境误操作;
- 优化 IInsert 批量插入容易导致 values 过多、或参数化过多的问题,5个数据库均已优化;
This commit is contained in:
28810
2019-03-14 02:24:15 +08:00
parent 1fa6c9bfc4
commit abb7402b36
47 changed files with 737 additions and 340 deletions

View File

@ -1,4 +1,5 @@
using FreeSql.Internal.Model;
using SafeObjectPool;
using System;
using System.Collections.Generic;
using System.Data;
@ -18,6 +19,7 @@ namespace FreeSql.Internal.CommonProvider {
protected Dictionary<string, bool> _ignore = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
protected TableInfo _table;
protected Func<string, string> _tableRule;
protected bool _noneParameter;
protected DbParameter[] _params;
protected DbTransaction _transaction;
@ -26,6 +28,7 @@ namespace FreeSql.Internal.CommonProvider {
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_table = _commonUtils.GetTableByEntity(typeof(T1));
_noneParameter = _orm.CodeFirst.IsNoneCommandParameter;
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure<T1>();
}
@ -33,6 +36,10 @@ namespace FreeSql.Internal.CommonProvider {
_transaction = transaction;
return this;
}
public IInsert<T1> NoneParameter() {
_noneParameter = false;
return this;
}
public IInsert<T1> AppendData(T1 source) {
if (source != null) _source.Add(source);
@ -43,8 +50,228 @@ namespace FreeSql.Internal.CommonProvider {
return this;
}
public virtual int ExecuteAffrows() => _orm.Ado.ExecuteNonQuery(_transaction, CommandType.Text, this.ToSql(), _params);
public virtual Task<int> ExecuteAffrowsAsync() => _orm.Ado.ExecuteNonQueryAsync(_transaction, CommandType.Text, this.ToSql(), _params);
#region values数量限制
internal List<T1>[] SplitSource(int valuesLimit, int parameterLimit) {
valuesLimit = valuesLimit - 1;
parameterLimit = parameterLimit - 1;
if (_source == null || _source.Any() == false) return new List<T1>[0];
if (_source.Count == 1) return new[] { _source };
if (_noneParameter) {
if (_source.Count < valuesLimit) return new[] { _source };
var execCount = (int)Math.Ceiling(1.0 * _source.Count / valuesLimit);
var ret = new List<T1>[execCount];
for (var a = 0; a < execCount; a++) {
var subSource = new List<T1>();
subSource = _source.GetRange(a * valuesLimit, Math.Min(valuesLimit, _source.Count - a * valuesLimit));
ret[a] = subSource;
}
return ret;
} else {
var colSum = _table.Columns.Count - _ignore.Count;
var takeMax = parameterLimit / colSum;
var pamTotal = colSum * _source.Count;
if (pamTotal < parameterLimit) return new[] { _source };
var execCount = (int)Math.Ceiling(1.0 * pamTotal / parameterLimit);
var ret = new List<T1>[execCount];
for (var a = 0; a < execCount; a++) {
var subSource = new List<T1>();
subSource = _source.GetRange(a * takeMax, Math.Min(takeMax, _source.Count - a * takeMax));
ret[a] = subSource;
}
return ret;
}
}
internal int SplitExecuteAffrows(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
if (ss.Any() == false) return 0;
if (ss.Length == 1) return this.RawExecuteAffrows();
var ret = 0;
if (_transaction != null) {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
ret += this.RawExecuteAffrows();
}
} else {
using (var conn = _orm.Ado.MasterPool.Get()) {
_transaction = conn.Value.BeginTransaction();
try {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
ret += this.RawExecuteAffrows();
}
_transaction.Commit();
} catch {
_transaction.Rollback();
throw;
}
_transaction = null;
}
}
return ret;
}
async internal Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
if (ss.Any() == false) return 0;
if (ss.Length == 1) return await this.RawExecuteAffrowsAsync();
var ret = 0;
if (_transaction != null) {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
ret += await this.RawExecuteAffrowsAsync();
}
} else {
using (var conn = await _orm.Ado.MasterPool.GetAsync()) {
_transaction = conn.Value.BeginTransaction();
try {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
ret += await this.RawExecuteAffrowsAsync();
}
_transaction.Commit();
} catch {
_transaction.Rollback();
throw;
}
_transaction = null;
}
}
return ret;
}
internal long SplitExecuteIdentity(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
if (ss.Any() == false) return 0;
if (ss.Length == 1) return this.RawExecuteIdentity();
long ret = 0;
if (_transaction != null) {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
if (a < ss.Length - 1) this.RawExecuteAffrows();
else ret = this.RawExecuteIdentity();
}
} else {
using (var conn = _orm.Ado.MasterPool.Get()) {
_transaction = conn.Value.BeginTransaction();
try {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
if (a < ss.Length - 1) this.RawExecuteAffrows();
else ret = this.RawExecuteIdentity();
}
_transaction.Commit();
} catch {
_transaction.Rollback();
throw;
}
_transaction = null;
}
}
return ret;
}
async internal Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
if (ss.Any() == false) return 0;
if (ss.Length == 1) return await this.RawExecuteIdentityAsync();
long ret = 0;
if (_transaction != null) {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
if (a < ss.Length - 1) await this.RawExecuteAffrowsAsync();
else ret = await this.RawExecuteIdentityAsync();
}
} else {
using (var conn = await _orm.Ado.MasterPool.GetAsync()) {
_transaction = conn.Value.BeginTransaction();
try {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
if (a < ss.Length - 1) await this.RawExecuteAffrowsAsync();
else ret = await this.RawExecuteIdentityAsync();
}
_transaction.Commit();
} catch {
_transaction.Rollback();
throw;
}
_transaction = null;
}
}
return ret;
}
internal List<T1> SplitExecuteInserted(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
if (ss.Any() == false) return new List<T1>();
if (ss.Length == 1) return this.RawExecuteInserted();
var ret = new List<T1>();
if (_transaction != null) {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
ret.AddRange(this.RawExecuteInserted());
}
} else {
using (var conn = _orm.Ado.MasterPool.Get()) {
_transaction = conn.Value.BeginTransaction();
try {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
ret.AddRange(this.RawExecuteInserted());
}
_transaction.Commit();
} catch {
_transaction.Rollback();
throw;
}
_transaction = null;
}
}
return ret;
}
async internal Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
if (ss.Any() == false) return new List<T1>();
if (ss.Length == 1) return await this.RawExecuteInsertedAsync();
var ret = new List<T1>();
if (_transaction != null) {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
ret.AddRange(await this.RawExecuteInsertedAsync());
}
} else {
using (var conn = await _orm.Ado.MasterPool.GetAsync()) {
_transaction = conn.Value.BeginTransaction();
try {
for (var a = 0; a < ss.Length; a++) {
_source = ss[a];
ret.AddRange(await this.RawExecuteInsertedAsync());
}
_transaction.Commit();
} catch {
_transaction.Rollback();
throw;
}
_transaction = null;
}
}
return ret;
}
#endregion
internal int RawExecuteAffrows() => _orm.Ado.ExecuteNonQuery(_transaction, CommandType.Text, ToSql(), _params);
internal Task<int> RawExecuteAffrowsAsync() => _orm.Ado.ExecuteNonQueryAsync(_transaction, CommandType.Text, ToSql(), _params);
internal abstract long RawExecuteIdentity();
internal abstract Task<long> RawExecuteIdentityAsync();
internal abstract List<T1> RawExecuteInserted();
internal abstract Task<List<T1>> RawExecuteInsertedAsync();
public virtual int ExecuteAffrows() => RawExecuteAffrows();
public virtual Task<int> ExecuteAffrowsAsync() => RawExecuteAffrowsAsync();
public abstract long ExecuteIdentity();
public abstract Task<long> ExecuteIdentityAsync();
public abstract List<T1> ExecuteInserted();
@ -81,9 +308,8 @@ namespace FreeSql.Internal.CommonProvider {
++colidx;
}
sb.Append(") VALUES");
//_params = new DbParameter[colidx * _source.Count];
_params = new DbParameter[0];
//_params = new DbParameter[colidx * 5]; //批量添加第5行起不使用参数化
_params = _noneParameter ? new DbParameter[0] : new DbParameter[colidx * _source.Count];
var specialParams = new List<DbParameter>();
var didx = 0;
foreach (var d in _source) {
if (didx > 0) sb.Append(", ");
@ -98,17 +324,19 @@ namespace FreeSql.Internal.CommonProvider {
if (col.Attribute.IsPrimary && (col.CsType == typeof(Guid) || col.CsType == typeof(Guid?))
&& (val == null || (Guid)val == Guid.Empty)) tryp.SetValue(d, val = FreeUtil.NewMongodbId());
}
//if (didx >= 5)
sb.Append(_commonUtils.GetNoneParamaterSqlValue(col.CsType, val));
//else {
// sb.Append(_commonUtils.QuoteWriteParamter(col.CsType, $"{_commonUtils.QuoteParamterName(col.CsName)}{didx}"));
// _params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}{didx}", col.CsType, val);
//}
if (_noneParameter)
sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.CsType, val));
else {
sb.Append(_commonUtils.QuoteWriteParamter(col.CsType, _commonUtils.QuoteParamterName($"{col.CsName}{didx}")));
_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}{didx}", col.CsType, val);
}
++colidx2;
}
sb.Append(")");
++didx;
}
if (_noneParameter && specialParams.Any())
_params = specialParams.ToArray();
return sb.ToString();
}
}

View File

@ -279,7 +279,7 @@ namespace FreeSql.Internal.CommonProvider {
public Func<DbDataReader, T1> Read { get; set; }
}
protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTree() {
return _dicGetAllFieldExpressionTree.GetOrAdd(string.Join("+", _tables.Select(a => $"{_commonUtils.DbName}-{a.Table.DbName}-{a.Alias}-{a.Type}")), s => {
return _dicGetAllFieldExpressionTree.GetOrAdd(string.Join("+", _tables.Select(a => $"{_orm.Ado.DataType}-{a.Table.DbName}-{a.Alias}-{a.Type}")), s => {
var tb1 = _tables.First().Table;
var type = tb1.TypeLazy ?? tb1.Type;
var props = tb1.Properties;

View File

@ -22,6 +22,7 @@ namespace FreeSql.Internal.CommonProvider {
protected StringBuilder _set = new StringBuilder();
protected List<DbParameter> _params = new List<DbParameter>();
protected List<DbParameter> _paramsSource = new List<DbParameter>();
protected bool _noneParameter;
protected DbTransaction _transaction;
public UpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) {
@ -29,6 +30,7 @@ namespace FreeSql.Internal.CommonProvider {
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_table = _commonUtils.GetTableByEntity(typeof(T1));
_noneParameter = _orm.CodeFirst.IsNoneCommandParameter;
this.Where(_commonUtils.WhereObject(_table, "", dywhere));
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure<T1>();
}
@ -37,6 +39,10 @@ namespace FreeSql.Internal.CommonProvider {
_transaction = transaction;
return this;
}
public IUpdate<T1> NoneParameter() {
_noneParameter = false;
return this;
}
public int ExecuteAffrows() {
var sql = this.ToSql();
@ -70,8 +76,13 @@ namespace FreeSql.Internal.CommonProvider {
_commonExpression.ExpressionSelectColumn_MemberAccess(null, cols, SelectTableInfoType.From, column?.Body, true, null);
if (cols.Count != 1) return this;
var col = cols.First();
_set.Append(", ").Append(_commonUtils.QuoteSqlName(col.Column.Attribute.Name)).Append(" = ").Append(_commonUtils.QuoteWriteParamter(col.Column.CsType, $"{_commonUtils.QuoteParamterName("p_")}{_params.Count}"));
_commonUtils.AppendParamter(_params, null, col.Column.CsType, value);
_set.Append(", ").Append(_commonUtils.QuoteSqlName(col.Column.Attribute.Name)).Append(" = ");
if (_noneParameter) {
_set.Append(_commonUtils.GetNoneParamaterSqlValue(_params, col.Column.CsType, value));
} else {
_set.Append(_commonUtils.QuoteWriteParamter(col.Column.CsType, $"{_commonUtils.QuoteParamterName("p_")}{_params.Count}"));
_commonUtils.AppendParamter(_params, null, col.Column.CsType, value);
}
//foreach (var t in _source) Utils.FillPropertyValue(t, tryf.CsName, value);
return this;
}
@ -131,8 +142,14 @@ namespace FreeSql.Internal.CommonProvider {
foreach (var col in _table.Columns.Values) {
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.CsName) == false) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(_commonUtils.QuoteWriteParamter(col.CsType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}")));
_commonUtils.AppendParamter(_paramsSource, null, col.CsType, _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(_source.First()) : null);
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ");
var value = _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(_source.First()) : null;
if (_noneParameter) {
sb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.CsType, value));
} else {
sb.Append(_commonUtils.QuoteWriteParamter(col.CsType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}")));
_commonUtils.AppendParamter(_paramsSource, null, col.CsType, value);
}
++colidx;
}
}
@ -171,8 +188,14 @@ namespace FreeSql.Internal.CommonProvider {
// ++pkidx;
//}
//if (_table.Primarys.Length > 1) sb.Append(")");
sb.Append(" THEN ").Append(_commonUtils.QuoteWriteParamter(col.CsType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}")));
_commonUtils.AppendParamter(_paramsSource, null, col.CsType, _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(d) : DBNull.Value);
sb.Append(" THEN ");
var value = _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(d) : DBNull.Value;
if (_noneParameter) {
sb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.CsType, value));
} else {
sb.Append(_commonUtils.QuoteWriteParamter(col.CsType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}")));
_commonUtils.AppendParamter(_paramsSource, null, col.CsType, value);
}
}
sb.Append(" END");
++colidx;