Merge branch 'master' into fix_tree

This commit is contained in:
2881099
2022-04-01 09:02:21 +08:00
committed by GitHub
244 changed files with 28531 additions and 407 deletions

View File

@@ -111,6 +111,7 @@ namespace FreeSql.Internal.CommonProvider
{
case DataType.Oracle:
case DataType.OdbcOracle:
case DataType.GBase:
ExecuteNonQuery(null, null, CommandType.Text, " SELECT 1 FROM dual", commandTimeout);
return true;
case DataType.Firebird:
@@ -581,7 +582,20 @@ namespace FreeSql.Internal.CommonProvider
if (availables.Any())
{
isSlave = true;
pool = availables.Count == 1 ? availables[0] : availables[slaveRandom.Next(availables.Count)];
if (availables.Count == 1) pool = availables[0];
else
{
var rnd = slaveRandom.Next(availables.Sum(a => a.Policy.Weight));
for(var a = 0; a < availables.Count; a++)
{
rnd -= availables[a].Policy.Weight;
if (rnd < 0)
{
pool = availables[a];
break;
}
}
}
}
}
}
@@ -851,6 +865,7 @@ namespace FreeSql.Internal.CommonProvider
if (cmdParms != null)
{
var dbpool = MasterPool as FreeSql.Internal.CommonProvider.DbConnectionPool;
foreach (var parm in cmdParms)
{
if (parm == null) continue;
@@ -871,7 +886,32 @@ namespace FreeSql.Internal.CommonProvider
});
}
}
if (isnew == false) cmd.Parameters.Add(parm);
if (isnew == false)
{
if (dbpool == null) cmd.Parameters.Add(parm);
else
{
var newparm = cmd.CreateParameter(); // UseConnectionFactory 转换 DbParameter
if (newparm.GetType() == parm.GetType()) cmd.Parameters.Add(parm);
else
{
newparm.DbType = parm.DbType;
newparm.Direction = parm.Direction;
newparm.ParameterName = parm.ParameterName;
#if net40 || net45
#else
newparm.Precision = parm.Precision;
newparm.Scale = parm.Scale;
#endif
newparm.Size = parm.Size;
newparm.SourceColumn = parm.SourceColumn;
newparm.SourceColumnNullMapping = parm.SourceColumnNullMapping;
newparm.SourceVersion = parm.SourceVersion;
newparm.Value = parm.Value;
cmd.Parameters.Add(newparm);
}
}
}
}
}

View File

@@ -25,6 +25,7 @@ namespace FreeSql.Internal.CommonProvider
{
case DataType.Oracle:
case DataType.OdbcOracle:
case DataType.GBase:
await ExecuteNonQueryAsync(null, null, CommandType.Text, " SELECT 1 FROM dual", commandTimeout, null, cancellationToken);
return true;
case DataType.Firebird:
@@ -78,7 +79,7 @@ namespace FreeSql.Internal.CommonProvider
}, cmdType, cmdText, cmdTimeout, cmdParms, cancellationToken);
return ret;
}
#region QueryAsync multi
#region QueryAsync multi
public Task<NativeTuple<List<T1>, List<T2>>> QueryAsync<T1, T2>(string cmdText, object parms = null, CancellationToken cancellationToken = default) => QueryAsync<T1, T2>(null, null, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
public Task<NativeTuple<List<T1>, List<T2>>> QueryAsync<T1, T2>(DbTransaction transaction, string cmdText, object parms = null, CancellationToken cancellationToken = default) => QueryAsync<T1, T2>(null, transaction, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
public Task<NativeTuple<List<T1>, List<T2>>> QueryAsync<T1, T2>(DbConnection connection, DbTransaction transaction, string cmdText, object parms = null, CancellationToken cancellationToken = default) => QueryAsync<T1, T2>(connection, transaction, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
@@ -468,7 +469,7 @@ namespace FreeSql.Internal.CommonProvider
}, null, cmdType, cmdText, cmdTimeout, cmdParms, cancellationToken);
return NativeTuple.Create(ret1, ret2, ret3, ret4, ret5);
}
#endregion
#endregion
public Task ExecuteReaderAsync(Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, string cmdText, object parms = null, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, null, fetchHandler, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
public Task ExecuteReaderAsync(DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, string cmdText, object parms = null, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, transaction, fetchHandler, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
@@ -476,7 +477,7 @@ namespace FreeSql.Internal.CommonProvider
public Task ExecuteReaderAsync(Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, CommandType cmdType, string cmdText, DbParameter[] cmdParms, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, null, fetchHandler, cmdType, cmdText, 0, cmdParms, cancellationToken);
public Task ExecuteReaderAsync(DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, CommandType cmdType, string cmdText, DbParameter[] cmdParms, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, transaction, fetchHandler, cmdType, cmdText, 0, cmdParms, cancellationToken);
public Task ExecuteReaderAsync(DbConnection connection, DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, CommandType cmdType, string cmdText, int cmdTimeout, DbParameter[] cmdParms, CancellationToken cancellationToken = default) => ExecuteReaderMultipleAsync(1, connection, transaction, (fetch, result) => fetchHandler(fetch), null, cmdType, cmdText, cmdTimeout, cmdParms, cancellationToken);
public async Task ExecuteReaderMultipleAsync(int multipleResult, DbConnection connection, DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, int, Task> fetchHandler, Action<DbDataReader, int> schemaHandler, CommandType cmdType, string cmdText, int cmdTimeout, DbParameter[] cmdParms, CancellationToken cancellationToken = default)
async public Task ExecuteReaderMultipleAsync(int multipleResult, DbConnection connection, DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, int, Task> fetchHandler, Action<DbDataReader, int> schemaHandler, CommandType cmdType, string cmdText, int cmdTimeout, DbParameter[] cmdParms, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(cmdText)) return;
var dt = DateTime.Now;
@@ -756,6 +757,7 @@ namespace FreeSql.Internal.CommonProvider
if (cmdParms != null)
{
var dbpool = MasterPool as FreeSql.Internal.CommonProvider.DbConnectionPool;
foreach (var parm in cmdParms)
{
if (parm == null) continue;
@@ -776,7 +778,32 @@ namespace FreeSql.Internal.CommonProvider
});
}
}
if (isnew == false) cmd.Parameters.Add(parm);
if (isnew == false)
{
if (dbpool == null) cmd.Parameters.Add(parm);
else
{
var newparm = cmd.CreateParameter(); // UseConnectionFactory 转换 DbParameter
if (newparm.GetType() == parm.GetType()) cmd.Parameters.Add(parm);
else
{
newparm.DbType = parm.DbType;
newparm.Direction = parm.Direction;
newparm.ParameterName = parm.ParameterName;
#if net40 || net45
#else
newparm.Precision = parm.Precision;
newparm.Scale = parm.Scale;
#endif
newparm.Size = parm.Size;
newparm.SourceColumn = parm.SourceColumn;
newparm.SourceColumnNullMapping = parm.SourceColumnNullMapping;
newparm.SourceVersion = parm.SourceVersion;
newparm.Value = parm.Value;
cmd.Parameters.Add(newparm);
}
}
}
}
}

View File

@@ -110,6 +110,7 @@ namespace FreeSql.Internal.CommonProvider
public bool IsThrowGetTimeoutException { get; set; } = true;
public bool IsAutoDisposeWithSystem { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5;
public int Weight { get; set; } = 1;
public DbConnection OnCreate()
{

View File

@@ -15,7 +15,11 @@ namespace FreeSql.Internal.CommonProvider
public ISelect<T1> Select<T1>() where T1 : class => CreateSelectProvider<T1>(null);
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => CreateSelectProvider<T1>(dywhere);
public IInsert<T1> Insert<T1>() where T1 : class => CreateInsertProvider<T1>();
public IInsert<T1> Insert<T1>() where T1 : class
{
if (typeof(T1) == typeof(Dictionary<string, object>)) throw new Exception("请使用 fsql.InsertDict(dict) 方法插入字典数据");
return CreateInsertProvider<T1>();
}
public IInsert<T1> Insert<T1>(T1 source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(T1[] source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(List<T1> source) where T1 : class => this.Insert<T1>().AppendData(source);

View File

@@ -94,7 +94,7 @@ namespace FreeSql.Internal.CommonProvider
protected void SyncStructure(params TypeAndName[] objects)
{
if (objects == null) return;
var syncObjects = objects.Where(a => a.entityType != typeof(object) && _dicSycedGetOrAdd(a.entityType).ContainsKey(GetTableNameLowerOrUpper(a.tableName)) == false && GetTableByEntity(a.entityType)?.DisableSyncStructure == false)
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();
if (syncObjects.Any() == false) return;
var before = new Aop.SyncStructureBeforeEventArgs(syncObjects.Select(a => a.entityType).ToArray());

View File

@@ -147,6 +147,11 @@ namespace FreeSql.Internal.CommonProvider
_tableRule = tableRule;
return this;
}
public IDelete<T1> AsTable(string tableName)
{
_tableRule = (oldname) => tableName;
return this;
}
public IDelete<T1> AsType(Type entityType)
{
if (entityType == typeof(object)) throw new Exception("IDelete.AsType 参数不支持指定为 object");
@@ -157,7 +162,7 @@ namespace FreeSql.Internal.CommonProvider
return this;
}
public string ToSql()
public virtual string ToSql()
{
if (_whereTimes <= 0) return null;
var sb = new StringBuilder().Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" WHERE ").Append(_where);

View File

@@ -29,7 +29,7 @@ namespace FreeSql.Internal.CommonProvider
public DbTransaction _transaction;
public DbConnection _connection;
public int _commandTimeout = 0;
public ColumnInfo IdentityColumn { get; }
public ColumnInfo IdentityColumn { get; private set; }
public InsertOrUpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
{
@@ -37,12 +37,10 @@ namespace FreeSql.Internal.CommonProvider
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_table = _commonUtils.GetTableByEntity(typeof(T1));
if (_table == null)
{
if (_table == null && typeof(T1) != typeof(Dictionary<string, object>))
throw new Exception($"InsertOrUpdate<>的泛型参数 不支持 {typeof(T1)},请传递您的实体类");
}
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
IdentityColumn = _table.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault();
IdentityColumn = _table?.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault();
}
protected void ClearData()
@@ -88,14 +86,14 @@ namespace FreeSql.Internal.CommonProvider
}
public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
{
if (data == null) return;
if (data == null || table == null) return;
if (typeof(T1) == typeof(object) && new[] { table.Type, table.TypeLazy }.Contains(data.GetType()) == false)
throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。");
if (orm.Aop.AuditValueHandler == null) return;
foreach (var col in table.Columns.Values)
{
object val = col.GetValue(data);
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.InsertOrUpdate, col, table.Properties[col.CsName], val);
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.InsertOrUpdate, col, table.Properties.TryGetValue(col.CsName, out var tryprop) ? tryprop : null, val);
orm.Aop.AuditValueHandler(sender, auditArgs);
if (auditArgs.ValueIsChanged)
{
@@ -112,6 +110,7 @@ namespace FreeSql.Internal.CommonProvider
public IInsertOrUpdate<T1> SetSource(IEnumerable<T1> source)
{
if (source == null || source.Any() == false) return this;
UpdateProvider<T1>.GetDictionaryTableInfo(source.FirstOrDefault(), _orm, ref _table);
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
_source.AddRange(source.Where(a => a != null));
return this;
@@ -139,6 +138,11 @@ namespace FreeSql.Internal.CommonProvider
_tableRule = tableRule;
return this;
}
public IInsertOrUpdate<T1> AsTable(string tableName)
{
_tableRule = (oldname) => tableName;
return this;
}
public IInsertOrUpdate<T1> AsType(Type entityType)
{
if (entityType == typeof(object)) throw new Exception("IInsertOrUpdate.AsType 参数不支持指定为 object");
@@ -146,6 +150,7 @@ namespace FreeSql.Internal.CommonProvider
var newtb = _commonUtils.GetTableByEntity(entityType);
_table = newtb ?? throw new Exception("IInsertOrUpdate.AsType 参数错误,请传入正确的实体类型");
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
IdentityColumn = _table.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault();
return this;
}
@@ -182,6 +187,7 @@ namespace FreeSql.Internal.CommonProvider
case DataType.Oracle:
case DataType.OdbcDameng:
case DataType.Dameng:
case DataType.GBase:
sb.Append(" FROM dual");
break;
case DataType.Firebird:

View File

@@ -9,6 +9,7 @@ using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace FreeSql.Internal.CommonProvider
{
@@ -115,6 +116,7 @@ namespace FreeSql.Internal.CommonProvider
{
if (source != null)
{
UpdateProvider<T1>.GetDictionaryTableInfo(source, _orm, ref _table);
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
_source.Add(source);
}
@@ -124,6 +126,7 @@ namespace FreeSql.Internal.CommonProvider
{
if (source != null)
{
UpdateProvider<T1>.GetDictionaryTableInfo(source.FirstOrDefault(), _orm, ref _table);
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
_source.AddRange(source);
}
@@ -134,6 +137,7 @@ namespace FreeSql.Internal.CommonProvider
if (source != null)
{
source = source.Where(a => a != null).ToList();
UpdateProvider<T1>.GetDictionaryTableInfo(source.FirstOrDefault(), _orm, ref _table);
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
_source.AddRange(source);
@@ -148,7 +152,7 @@ namespace FreeSql.Internal.CommonProvider
}
public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
{
if (data == null) return;
if (data == null || table == null) return;
if (typeof(T1) == typeof(object) && new[] { table.Type, table.TypeLazy }.Contains(data.GetType()) == false)
throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。");
foreach (var col in table.Columns.Values)
@@ -156,7 +160,7 @@ namespace FreeSql.Internal.CommonProvider
object val = col.GetValue(data);
if (orm.Aop.AuditValueHandler != null)
{
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Insert, col, table.Properties[col.CsName], val);
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Insert, col, table.Properties.TryGetValue(col.CsName, out var tryprop) ? tryprop : null, val);
orm.Aop.AuditValueHandler(sender, auditArgs);
if (auditArgs.ValueIsChanged)
{
@@ -210,7 +214,7 @@ namespace FreeSql.Internal.CommonProvider
ret[a] = _source.GetRange(a * takeMax, Math.Min(takeMax, _source.Count - a * takeMax));
return ret;
}
protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
protected virtual int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
@@ -505,13 +509,14 @@ namespace FreeSql.Internal.CommonProvider
protected string TableRuleInvoke()
{
if (_tableRule == null) return _table.DbName;
var newname = _tableRule(_table.DbName);
if (newname == _table.DbName) return _table.DbName;
if (string.IsNullOrEmpty(newname)) return _table.DbName;
var tbname = _table?.DbName ?? "";
if (_tableRule == null) return tbname;
var newname = _tableRule(tbname);
if (newname == tbname) return tbname;
if (string.IsNullOrEmpty(newname)) return tbname;
if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower();
if (_orm.CodeFirst.IsSyncStructureToUpper) newname = newname.ToUpper();
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname);
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table?.Type, newname);
return newname;
}
public IInsert<T1> AsTable(Func<string, string> tableRule)
@@ -519,6 +524,11 @@ namespace FreeSql.Internal.CommonProvider
_tableRule = tableRule;
return this;
}
public IInsert<T1> AsTable(string tableName)
{
_tableRule = (oldname) => tableName;
return this;
}
public IInsert<T1> AsType(Type entityType)
{
if (entityType == typeof(object)) throw new Exception("IInsert.AsType 参数不支持指定为 object");

View File

@@ -17,7 +17,7 @@ namespace FreeSql.Internal.CommonProvider
{
#if net40
#else
async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
async protected virtual Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
@@ -96,7 +96,7 @@ namespace FreeSql.Internal.CommonProvider
return ret;
}
async protected Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
async protected virtual Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{
var ss = SplitSource(valuesLimit, parameterLimit);
long ret = 0;
@@ -177,7 +177,7 @@ namespace FreeSql.Internal.CommonProvider
return ret;
}
async protected Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
async protected virtual Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();

View File

@@ -352,6 +352,7 @@ namespace FreeSql.Internal.CommonProvider
case DataType.Oracle:
case DataType.OdbcOracle:
case DataType.Firebird:
case DataType.GBase:
break;
default:
_select = "SELECT ";
@@ -407,6 +408,7 @@ namespace FreeSql.Internal.CommonProvider
case DataType.Oracle:
case DataType.OdbcOracle:
case DataType.Firebird:
case DataType.GBase:
break;
default:
var beforeSql = this._select;
@@ -440,6 +442,7 @@ namespace FreeSql.Internal.CommonProvider
case DataType.Oracle:
case DataType.OdbcOracle:
case DataType.Firebird:
case DataType.GBase:
break;
default:
var beforeSql = this._select;
@@ -544,17 +547,35 @@ namespace FreeSql.Internal.CommonProvider
{
if (string.IsNullOrEmpty(fi.Field) == false)
{
Expression exp = ConvertStringPropertyToExpression(fi.Field);
Expression exp = null;
switch (fi.Operator)
{
case DynamicFilterOperator.Custom:
var fiValueCustomArray = fi.Field?.ToString().Split(new[] { ' ' }, 2);
if (fiValueCustomArray.Length != 2) throw new ArgumentException("Custom 要求 Field 应该空格分割,并且长度为 2格式{静态方法名}{空格}{反射信息}");
if (string.IsNullOrWhiteSpace(fiValueCustomArray[0])) throw new ArgumentException("Custom {静态方法名}不能为空,格式:{静态方法名}{空格}{反射信息}");
if (string.IsNullOrWhiteSpace(fiValueCustomArray[1])) throw new ArgumentException("Custom {反射信息}不能为空,格式:{静态方法名}{空格}{反射信息}");
var fiValue1Type = Type.GetType(fiValueCustomArray[1]);
if (fiValue1Type == null) throw new ArgumentException($"Custom 找不到对应的{{反射信息}}{fiValueCustomArray[1]}");
var fiValue0Method = fiValue1Type.GetMethod(fiValueCustomArray[0], new Type[] { typeof(string) });
if (fiValue0Method == null) throw new ArgumentException($"Custom 找不到对应的{{静态方法名}}{fiValueCustomArray[0]}");
if (MethodIsDynamicFilterCustomAttribute(fiValue0Method) == false) throw new ArgumentException($"Custom 对应的{{静态方法名}}{fiValueCustomArray[0]} 未设置 [DynamicFilterCustomAttribute] 特性");
var fiValue0MethodReturn = fiValue0Method?.Invoke(null, new object[] { fi.Value?.ToString() })?.ToString();
exp = Expression.Call(typeof(SqlExt).GetMethod("InternalRawSql", BindingFlags.NonPublic | BindingFlags.Static), Expression.Constant(fiValue0MethodReturn, typeof(string)));
break;
case DynamicFilterOperator.Contains:
case DynamicFilterOperator.StartsWith:
case DynamicFilterOperator.EndsWith:
case DynamicFilterOperator.NotContains:
case DynamicFilterOperator.NotStartsWith:
case DynamicFilterOperator.NotEndsWith:
exp = ConvertStringPropertyToExpression(fi.Field);
if (exp.Type != typeof(string)) exp = Expression.TypeAs(exp, typeof(string));
break;
default:
exp = ConvertStringPropertyToExpression(fi.Field);
break;
}
switch (fi.Operator)
{
@@ -579,7 +600,7 @@ namespace FreeSql.Internal.CommonProvider
if (fiValueRangeArray.Length != 2) throw new ArgumentException($"Range 要求 Value 应该逗号分割,并且长度为 2");
exp = Expression.AndAlso(
Expression.GreaterThanOrEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[0]), exp.Type)),
Expression.LessThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[1]), exp.Type)));
Expression.LessThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[1]), exp.Type)));
break;
case DynamicFilterOperator.DateRange:
var fiValueDateRangeArray = getFiListValue();
@@ -676,6 +697,21 @@ namespace FreeSql.Internal.CommonProvider
string.IsNullOrEmpty(testFilter.Value?.ToString());
}
}
static ConcurrentDictionary<MethodInfo, bool> _dicMethodIsDynamicFilterCustomAttribute = new ConcurrentDictionary<MethodInfo, bool>();
static bool MethodIsDynamicFilterCustomAttribute(MethodInfo method) => _dicMethodIsDynamicFilterCustomAttribute.GetOrAdd(method, m =>
{
object[] attrs = null;
try
{
attrs = m.GetCustomAttributes(false).ToArray(); //.net core 反射存在版本冲突问题,导致该方法异常
}
catch { }
var dyattr = attrs?.Where(a => {
return ((a as Attribute)?.TypeId as Type)?.Name == "DynamicFilterCustomAttribute";
}).FirstOrDefault();
return dyattr != null;
});
public TSelect DisableGlobalFilter(params string[] name)
{
@@ -722,6 +758,7 @@ namespace FreeSql.Internal.CommonProvider
break;
case DataType.Sqlite:
break;
case DataType.GBase:
case DataType.ShenTong: //神通测试中发现,不支持 nowait
_tosqlAppendContent = $"{_tosqlAppendContent} for update";
break;

View File

@@ -19,6 +19,25 @@ namespace FreeSql.Internal.CommonProvider
{
partial class Select0Provider<TSelect, T1>
{
public DataTable ToDataTableByPropertyName(string[] properties)
{
if (properties?.Any() != true) throw new ArgumentException($"properties 参数不能为空");
var sbfield = new StringBuilder();
for (var propIdx = 0; propIdx < properties.Length; propIdx++)
{
var property = properties[propIdx];
var exp = ConvertStringPropertyToExpression(property);
if (exp == null) throw new Exception($"{property} 属性名无法找到");
var field = _commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null);
if (propIdx > 0) sbfield.Append(", ");
sbfield.Append(field);
//if (field != property)
sbfield.Append(_commonUtils.FieldAsAlias(_commonUtils.QuoteSqlName("test").Replace("test", property)));
}
var sbfieldStr = sbfield.ToString();
sbfield.Clear();
return ToDataTable(sbfieldStr);
}
public DataTable ToDataTable(string field = null)
{
DataTable ret = null;
@@ -514,7 +533,7 @@ namespace FreeSql.Internal.CommonProvider
});
}
static EventHandler<Aop.AuditDataReaderEventArgs> _OldAuditDataReaderHandler;
public GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevel2()
public GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevel2(bool isRereadSql = true)
{
if (_selectExpression != null) //ToSql
{
@@ -530,7 +549,7 @@ namespace FreeSql.Internal.CommonProvider
_OldAuditDataReaderHandler = _orm.Aop.AuditDataReaderHandler; //清除单表 ExppressionTree
_dicGetAllFieldExpressionTree.TryRemove($"{_orm.Ado.DataType}-{_tables[0].Table.DbName}-{_tables[0].Table.Type.FullName}-{_tables[0].Alias}-{_tables[0].Type}", out var oldet);
}
return _dicGetAllFieldExpressionTree.GetOrAdd(string.Join("+", _tables.Select(a => $"{_orm.Ado.DataType}-{a.Table.DbName}-{a.Table.Type.FullName}-{a.Alias}-{a.Type}")), s =>
return _dicGetAllFieldExpressionTree.GetOrAdd(string.Join("+", _tables.Select(a => $"{_orm.Ado.DataType}-{a.Table.DbName}-{a.Table.Type.FullName}-{a.Alias}-{a.Type}-{(isRereadSql ? 1 : 0)}")), s =>
{
var tb1 = _tables.First().Table;
var type = tb1.TypeLazy ?? tb1.Type;
@@ -564,7 +583,8 @@ namespace FreeSql.Internal.CommonProvider
{ //普通字段
if (index > 0) field.Append(", ");
var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
field.Append(_commonUtils.RereadColumn(col, $"{tb.Alias}.{quoteName}"));
if (isRereadSql) field.Append(_commonUtils.RereadColumn(col, $"{tb.Alias}.{quoteName}"));
else field.Append($"{tb.Alias}.{quoteName}");
++index;
if (dicfield.ContainsKey(quoteName)) field.Append(_commonUtils.FieldAsAlias($"as{index}"));
else dicfield.Add(quoteName, true);
@@ -587,7 +607,8 @@ namespace FreeSql.Internal.CommonProvider
{
if (index > 0) field.Append(", ");
var quoteName = _commonUtils.QuoteSqlName(col2.Attribute.Name);
field.Append(_commonUtils.RereadColumn(col2, $"{tb2.Alias}.{quoteName}"));
if (isRereadSql) field.Append(_commonUtils.RereadColumn(col2, $"{tb2.Alias}.{quoteName}"));
else field.Append($"{tb2.Alias}.{quoteName}");
++index;
++otherindex;
if (dicfield.ContainsKey(quoteName)) field.Append(_commonUtils.FieldAsAlias($"as{index}"));
@@ -760,8 +781,32 @@ namespace FreeSql.Internal.CommonProvider
_commonExpression.ExpressionJoinLambda(_tables, joinType, exp, null, _whereGlobalFilter);
return this as TSelect;
}
protected TSelect InternalOrderBy(Expression column) => this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null));
protected TSelect InternalOrderByDescending(Expression column) => this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC");
protected TSelect InternalOrderBy(Expression column)
{
if (column.NodeType == ExpressionType.Lambda) column = (column as LambdaExpression)?.Body;
switch (column?.NodeType)
{
case ExpressionType.New:
var newExp = column as NewExpression;
if (newExp == null) break;
for (var a = 0; a < newExp.Members.Count; a++) this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, newExp.Arguments[a], true, null));
return this as TSelect;
}
return this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null));
}
protected TSelect InternalOrderByDescending(Expression column)
{
if (column.NodeType == ExpressionType.Lambda) column = (column as LambdaExpression)?.Body;
switch (column?.NodeType)
{
case ExpressionType.New:
var newExp = column as NewExpression;
if (newExp == null) break;
for (var a = 0; a < newExp.Members.Count; a++) this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, newExp.Arguments[a], true, null)} DESC");
return this as TSelect;
}
return this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC");
}
public List<TReturn> InternalToList<TReturn>(Expression select) => this.ToListMapReader<TReturn>(this.GetExpressionField(select));
protected string InternalToSql<TReturn>(Expression select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex)
@@ -876,6 +921,25 @@ namespace FreeSql.Internal.CommonProvider
#region Async
#if net40
#else
public Task<DataTable> ToDataTableByPropertyNameAsync(string[] properties, CancellationToken cancellationToken)
{
if (properties?.Any() != true) throw new ArgumentException($"properties 参数不能为空");
var sbfield = new StringBuilder();
for (var propIdx = 0; propIdx < properties.Length; propIdx++)
{
var property = properties[propIdx];
var exp = ConvertStringPropertyToExpression(property);
if (exp == null) throw new Exception($"{property} 属性名无法找到");
var field = _commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null);
if (propIdx > 0) sbfield.Append(", ");
sbfield.Append(field);
//if (field != property)
sbfield.Append(_commonUtils.FieldAsAlias(_commonUtils.QuoteSqlName("test").Replace("test", property)));
}
var sbfieldStr = sbfield.ToString();
sbfield.Clear();
return ToDataTableAsync(sbfieldStr, cancellationToken);
}
async public Task<DataTable> ToDataTableAsync(string field, CancellationToken cancellationToken)
{
DataTable ret = null;

View File

@@ -96,6 +96,15 @@ namespace FreeSql.Internal.CommonProvider
}
public void InternalOrderBy(Expression exp, bool isDescending)
{
if (exp.NodeType == ExpressionType.Lambda) exp = (exp as LambdaExpression)?.Body;
if (exp?.NodeType == ExpressionType.New)
{
var newExp = exp as NewExpression;
if (newExp != null)
for (var a = 0; a < newExp.Members.Count; a++)
InternalOrderBy(newExp.Arguments[a], isDescending);
return;
}
var sql = _comonExp.ExpressionWhereLambda(null, exp, this, null, null);
var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) });
method.Invoke(_select, new object[] { isDescending ? $"{sql} DESC" : sql, null });
@@ -150,6 +159,7 @@ namespace FreeSql.Internal.CommonProvider
case DataType.OdbcOracle:
case DataType.Dameng:
case DataType.OdbcDameng: //Oracle、Dameng 分组时,嵌套分页
case DataType.GBase:
isNestedPageSql = true;
break;
default:

View File

@@ -46,7 +46,7 @@ namespace FreeSql.Internal.CommonProvider
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_table = _commonUtils.GetTableByEntity(typeof(T1));
_tempPrimarys = _table.Primarys;
_tempPrimarys = _table?.Primarys ?? new ColumnInfo[0];
_noneParameter = _orm.CodeFirst.IsNoneCommandParameter;
this.Where(_commonUtils.WhereObject(_table, "", dywhere));
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
@@ -60,7 +60,7 @@ namespace FreeSql.Internal.CommonProvider
protected void IgnoreCanUpdate()
{
if (_table == null || _table.Type == typeof(object)) return;
foreach (var col in _table.Columns.Values)
foreach (var col in _table?.Columns.Values)
if (col.Attribute.CanUpdate == false && _ignore.ContainsKey(col.Attribute.Name) == false)
_ignore.Add(col.Attribute.Name, true);
}
@@ -138,7 +138,7 @@ namespace FreeSql.Internal.CommonProvider
}
#region values数量限制
internal List<T1>[] SplitSource(int valuesLimit, int parameterLimit)
protected internal List<T1>[] SplitSource(int valuesLimit, int parameterLimit)
{
valuesLimit = valuesLimit - 1;
parameterLimit = parameterLimit - 1;
@@ -163,7 +163,7 @@ namespace FreeSql.Internal.CommonProvider
ret[a] = _source.GetRange(a * takeMax, Math.Min(takeMax, _source.Count - a * takeMax));
return ret;
}
protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
protected virtual int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
@@ -237,7 +237,7 @@ namespace FreeSql.Internal.CommonProvider
return ret;
}
protected List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit)
protected virtual List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();
@@ -377,7 +377,7 @@ namespace FreeSql.Internal.CommonProvider
foreach (var col in table.Columns.Values)
{
object val = col.GetValue(d);
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties[col.CsName], val);
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties.TryGetValue(col.CsName, out var tryprop) ? tryprop : null, val);
orm.Aop.AuditValueHandler(sender, auditArgs);
if (auditArgs.ValueIsChanged)
{
@@ -393,13 +393,13 @@ namespace FreeSql.Internal.CommonProvider
public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
{
if (orm.Aop.AuditValueHandler == null) return;
if (data == null) return;
if (data == null || table == null) return;
if (typeof(T1) == typeof(object) && new[] { table.Type, table.TypeLazy }.Contains(data.GetType()) == false)
throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。");
foreach (var col in table.Columns.Values)
{
object val = col.GetValue(data);
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties[col.CsName], val);
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties.TryGetValue(col.CsName, out var tryprop) ? tryprop : null, val);
orm.Aop.AuditValueHandler(sender, auditArgs);
if (auditArgs.ValueIsChanged)
{
@@ -412,10 +412,49 @@ namespace FreeSql.Internal.CommonProvider
}
}
public static void GetDictionaryTableInfo(T1 source, IFreeSql orm, ref TableInfo table)
{
if (table == null && typeof(T1) == typeof(Dictionary<string, object>))
{
if (source == null) throw new ArgumentNullException(nameof(source));
var dic = source as Dictionary<string, object>;
table = new TableInfo();
table.Type = typeof(Dictionary<string, object>);
table.CsName = dic.TryGetValue("", out var tryval) ? string.Concat(tryval) : "";
table.DbName = table.CsName;
table.DisableSyncStructure = true;
table.IsDictionaryType = true;
var colpos = new List<ColumnInfo>();
foreach (var kv in dic)
{
var colName = kv.Key;
if (orm.CodeFirst.IsSyncStructureToLower) colName = colName.ToLower();
if (orm.CodeFirst.IsSyncStructureToUpper) colName = colName.ToUpper();
var col = new ColumnInfo
{
CsName = kv.Key,
Table = table,
Attribute = new DataAnnotations.ColumnAttribute
{
Name = colName,
MapType = typeof(object)
},
CsType = typeof(object)
};
table.Columns.Add(colName, col);
table.ColumnsByCs.Add(kv.Key, col);
colpos.Add(col);
}
table.ColumnsByPosition = colpos.ToArray();
colpos.Clear();
}
}
public IUpdate<T1> SetSource(T1 source) => this.SetSource(new[] { source });
public IUpdate<T1> SetSource(IEnumerable<T1> source, Expression<Func<T1, object>> tempPrimarys = null)
{
if (source == null || source.Any() == false) return this;
GetDictionaryTableInfo(source.FirstOrDefault(), _orm, ref _table);
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
_source.AddRange(source.Where(a => a != null));
@@ -445,7 +484,7 @@ namespace FreeSql.Internal.CommonProvider
_set.Append(", ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ");
var colsql = _noneParameter ? _commonUtils.GetNoneParamaterSqlValue(_params, "u", col, col.Attribute.MapType, val) :
_commonUtils.QuoteWriteParamterAdapter(col.Attribute.MapType, $"{_commonUtils.QuoteParamterName("p_")}{_params.Count}");
_commonUtils.QuoteWriteParamterAdapter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_params.Count}"));
_set.Append(_commonUtils.RewriteColumn(col, colsql));
if (_noneParameter == false)
_commonUtils.AppendParamter(_params, null, col, col.Attribute.MapType, val);
@@ -487,7 +526,8 @@ namespace FreeSql.Internal.CommonProvider
var memberName = initExp.Bindings[a].Member.Name;
if (_table.ColumnsByCsIgnore.ContainsKey(memberName)) continue;
if (_table.ColumnsByCs.TryGetValue(memberName, out var col) == false) throw new Exception($"找不到属性:{memberName}");
var memberValue = _commonExpression.ExpressionLambdaToSql(initAssignExp.Expression, new CommonExpression.ExpTSC { isQuoteName = true, mapType = col.Attribute.MapType });
var memberValue = _commonExpression.ExpressionLambdaToSql(initAssignExp.Expression, new CommonExpression.ExpTSC { isQuoteName = true,
mapType = initAssignExp.Expression is BinaryExpression ? null : col.Attribute.MapType });
_setIncr.Append(", ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(memberValue);
}
}
@@ -501,7 +541,8 @@ namespace FreeSql.Internal.CommonProvider
var memberName = newExp.Members[a].Name;
if (_table.ColumnsByCsIgnore.ContainsKey(memberName)) continue;
if (_table.ColumnsByCs.TryGetValue(memberName, out var col) == false) throw new Exception($"找不到属性:{memberName}");
var memberValue = _commonExpression.ExpressionLambdaToSql(newExp.Arguments[a], new CommonExpression.ExpTSC { isQuoteName = true, mapType = col.Attribute.MapType });
var memberValue = _commonExpression.ExpressionLambdaToSql(newExp.Arguments[a], new CommonExpression.ExpTSC { isQuoteName = true,
mapType = newExp.Arguments[a] is BinaryExpression ? null : col.Attribute.MapType });
_setIncr.Append(", ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(memberValue);
}
}
@@ -665,6 +706,11 @@ namespace FreeSql.Internal.CommonProvider
_tableRule = tableRule;
return this;
}
public IUpdate<T1> AsTable(string tableName)
{
_tableRule = (oldname) => tableName;
return this;
}
public IUpdate<T1> AsType(Type entityType)
{
if (entityType == typeof(object)) throw new Exception("IUpdate.AsType 参数不支持指定为 object");

View File

@@ -18,7 +18,7 @@ namespace FreeSql.Internal.CommonProvider
{
#if net40
#else
async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
async protected virtual Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
@@ -91,7 +91,7 @@ namespace FreeSql.Internal.CommonProvider
ClearData();
return ret;
}
async protected Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
async protected virtual Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();