diff --git a/Examples/base_entity/MessagePackMap.cs b/Examples/base_entity/MessagePackMap.cs index 9767a40c0..cfc00b6ab 100644 --- a/Examples/base_entity/MessagePackMap.cs +++ b/Examples/base_entity/MessagePackMap.cs @@ -20,7 +20,7 @@ public class MessagePackMap01 [Key(0)] public string name { get; set; } [Key(1)] - public string address { get;set; } + public string address { get; set; } } namespace FreeSql.DataAnnotations @@ -31,10 +31,10 @@ public class MessagePackMapAttribute : Attribute { } public static class FreeSqlMessagePackMapCoreExtensions { internal static int _isAoped = 0; - static ConcurrentDictionary _dicTypes = new ConcurrentDictionary(); + static ConcurrentDictionary _dicTypes =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem>(); static MethodInfo MethodMessagePackSerializerDeserialize = typeof(MessagePackSerializer).GetMethod("Deserialize", new[] { typeof(Type), typeof(ReadOnlyMemory), typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); static MethodInfo MethodMessagePackSerializerSerialize = typeof(MessagePackSerializer).GetMethod("Serialize", new[] { typeof(Type), typeof(object), typeof(MessagePackSerializerOptions), typeof(CancellationToken) }); - static ConcurrentDictionary> _dicMessagePackMapFluentApi = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicMessagePackMapFluentApi =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem>>(); static object _concurrentObj = new object(); public static ColumnFluent MessagePackMap(this ColumnFluent col) @@ -55,7 +55,7 @@ public static void UseMessagePackMap(this IFreeSql that, MessagePackSerializerOp { FreeSql.Internal.Utils.GetDataReaderValueBlockExpressionSwitchTypeFullName.Add((LabelTarget returnTarget, Expression valueExp, Type type) => { - if (_dicTypes.ContainsKey(type)) + if (_dicTypes.ContainsKey(type)) return Expression.IfThenElse( Expression.TypeIs(valueExp, type), Expression.Return(returnTarget, valueExp), diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootUtils.cs b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootUtils.cs index a79f9af51..a9cf1f23e 100644 --- a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootUtils.cs +++ b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootUtils.cs @@ -18,7 +18,8 @@ namespace FreeSql { public class AggregateRootUtils { - static ConcurrentDictionary> _dicGetPropertyBoundaryAttribute = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicGetPropertyBoundaryAttribute + = Utils.GlobalCacheFactory.CreateCacheItem>>(); public static AggregateRootBoundaryAttribute GetPropertyBoundaryAttribute(PropertyInfo prop, string boundaryName) { if (boundaryName == null) return null; @@ -161,7 +162,7 @@ void LocalCompareEntityValueCollection(Type elementType, IEnumerable collectionB { if (dictAfter.ContainsKey(key) == false) dictAfter.Add(key, item); - else if (key == "0" && table.Primarys.Length == 1 && + else if (key == "0" && table.Primarys.Length == 1 && new[] { typeof(long), typeof(int) }.Contains(table.Primarys[0].CsType)) tracking.InsertLog.Add(NativeTuple.Create(elementType, item)); } @@ -215,8 +216,9 @@ public static bool CompareEntityPropertyValue(Type type, object propvalBefore, o if (propvalBefore == null && propvalAfter != null) return false; if (propvalBefore != null && propvalAfter == null) return false; - if (FreeSql.Internal.Utils.dicExecuteArrayRowReadClassOrTuple.ContainsKey(type)) { - if (type.FullName.StartsWith("Newtonsoft.")) + if (FreeSql.Internal.Utils.dicExecuteArrayRowReadClassOrTuple.ContainsKey(type)) + { + if (type.FullName.StartsWith("Newtonsoft.")) return object.Equals(propvalBefore.ToString(), propvalAfter.ToString()); if (typeof(IDictionary).IsAssignableFrom(type)) @@ -261,7 +263,7 @@ public static bool CompareEntityPropertyValue(Type type, object propvalBefore, o if (type.FullName.StartsWith("System.") || type.FullName.StartsWith("Npgsql.") || - type.FullName.StartsWith("NetTopologySuite.")) + type.FullName.StartsWith("NetTopologySuite.")) return object.Equals(propvalBefore, propvalAfter); if (type.IsClass) @@ -434,7 +436,8 @@ void LocalMapEntityValueCollection(Type entityType, object entityFrom, object en } } - static ConcurrentDictionary>>> _dicGetAutoIncludeQuery = new ConcurrentDictionary>>>(); + static ConcurrentDictionary>>> _dicGetAutoIncludeQuery + = Utils.GlobalCacheFactory.CreateCacheItem>>>>(); public static ISelect GetAutoIncludeQuery(string boundaryName, ISelect select) { var select0p = select as Select0Provider; @@ -644,8 +647,8 @@ public static void SetNavigateRelationshipValue(IFreeSql orm, TableRef tbref, Ty case TableRefType.ManyToOne: for (var idx = 0; idx < tbref.RefColumns.Count; idx++) { - var colval = rightItem == null ? - tbref.Columns[idx].CsType.CreateInstanceGetDefaultValue() : + var colval = rightItem == null ? + tbref.Columns[idx].CsType.CreateInstanceGetDefaultValue() : Utils.GetDataReaderValue(tbref.Columns[idx].CsType, EntityUtilExtensions.GetEntityValueWithPropertyName(orm, tbref.RefEntityType, rightItem, tbref.RefColumns[idx].CsName)); EntityUtilExtensions.SetEntityValueWithPropertyName(orm, leftType, leftItem, tbref.Columns[idx].CsName, colval); } diff --git a/Extensions/FreeSql.Extensions.JsonMap/JsonMapCore.cs b/Extensions/FreeSql.Extensions.JsonMap/JsonMapCore.cs index 4ba6cc870..0490ede37 100644 --- a/Extensions/FreeSql.Extensions.JsonMap/JsonMapCore.cs +++ b/Extensions/FreeSql.Extensions.JsonMap/JsonMapCore.cs @@ -10,10 +10,10 @@ public static class FreeSqlJsonMapCoreExtensions { static int _isAoped = 0; - static ConcurrentDictionary _dicTypes = new ConcurrentDictionary(); + static ConcurrentDictionary _dicTypes =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem>(); static MethodInfo MethodJsonConvertDeserializeObject = typeof(JsonConvert).GetMethod("DeserializeObject", new[] { typeof(string), typeof(Type) }); static MethodInfo MethodJsonConvertSerializeObject = typeof(JsonConvert).GetMethod("SerializeObject", new[] { typeof(object), typeof(JsonSerializerSettings) }); - static ConcurrentDictionary> _dicJsonMapFluentApi = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicJsonMapFluentApi =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem>>(); static object _concurrentObj = new object(); public static ColumnFluent JsonMap(this ColumnFluent col) diff --git a/FreeSql.DbContext/DbContext/DbContextAsync.cs b/FreeSql.DbContext/DbContext/DbContextAsync.cs index 811ecfe74..979f36134 100644 --- a/FreeSql.DbContext/DbContext/DbContextAsync.cs +++ b/FreeSql.DbContext/DbContext/DbContextAsync.cs @@ -1,4 +1,5 @@ -using System; +using FreeSql.Internal; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -19,7 +20,7 @@ public virtual async Task SaveChangesAsync(CancellationToken cancellationTo return SaveChangesSuccess(); } - static ConcurrentDictionary>>> _dicFlushCommandDbSetBatchAsync = new ConcurrentDictionary>>>(); + static ConcurrentDictionary>>> _dicFlushCommandDbSetBatchAsync = Utils.GlobalCacheFactory.CreateCacheItem>>>>(); internal async Task FlushCommandAsync(CancellationToken cancellationToken) { if (isFlushCommanding) return; diff --git a/FreeSql.DbContext/DbContext/DbContextSync.cs b/FreeSql.DbContext/DbContext/DbContextSync.cs index 7b4fde35a..89c43dcc5 100644 --- a/FreeSql.DbContext/DbContext/DbContextSync.cs +++ b/FreeSql.DbContext/DbContext/DbContextSync.cs @@ -31,7 +31,7 @@ public virtual int SaveChanges() return SaveChangesSuccess(); } - static ConcurrentDictionary>> _dicFlushCommandDbSetBatch = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicFlushCommandDbSetBatch = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem>>>(); bool isFlushCommanding = false; /// /// 刷新队列中的命令 diff --git a/FreeSql.DbContext/DbSet/DbSetSync.cs b/FreeSql.DbContext/DbSet/DbSetSync.cs index 41417a0a0..798b8075a 100644 --- a/FreeSql.DbContext/DbSet/DbSetSync.cs +++ b/FreeSql.DbContext/DbSet/DbSetSync.cs @@ -377,7 +377,7 @@ void AddOrUpdateNavigate(TEntity item, bool isAdd, string propertyName) else if (_table.Properties.TryGetValue(propertyName, out var prop)) action(prop); } - static ConcurrentDictionary> _dicLazyIsSetField = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicLazyIsSetField = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem>>(); object GetItemValue(TEntity item, PropertyInfo prop) { object propVal = null; diff --git a/FreeSql.DbContext/Extensions/FreeSqlDbContextExtensions.cs b/FreeSql.DbContext/Extensions/FreeSqlDbContextExtensions.cs index 60a7394f3..43a3a3fca 100644 --- a/FreeSql.DbContext/Extensions/FreeSqlDbContextExtensions.cs +++ b/FreeSql.DbContext/Extensions/FreeSqlDbContextExtensions.cs @@ -40,5 +40,5 @@ public static IFreeSql SetDbContextOptions(this IFreeSql that, Action cfg); return that; } - internal static ConcurrentDictionary _dicSetDbContextOptions = new ConcurrentDictionary(); + internal static ConcurrentDictionary _dicSetDbContextOptions = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem>(); } \ No newline at end of file diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 197e64800..7b498789c 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -759,15 +759,6 @@ - - - 根据Assembly扫描所有继承IEntityTypeConfiguration<T>的配置类 - - - - - - 创建普通数据上下文档对象 @@ -826,14 +817,5 @@ - - - 批量注入 Repository,可以参考代码自行调整 - - - - - - diff --git a/FreeSql.DbContext/Repository/ContextSet/RepositoryDbContext.cs b/FreeSql.DbContext/Repository/ContextSet/RepositoryDbContext.cs index be0616a63..10a2025d8 100644 --- a/FreeSql.DbContext/Repository/ContextSet/RepositoryDbContext.cs +++ b/FreeSql.DbContext/Repository/ContextSet/RepositoryDbContext.cs @@ -18,7 +18,7 @@ public RepositoryDbContext(IFreeSql orm, IBaseRepository repo) : base() _repo = repo; } - static ConcurrentDictionary> _dicGetRepositoryDbField = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicGetRepositoryDbField = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem>>(); static FieldInfo GetRepositoryDbField(Type type, string fieldName) => _dicGetRepositoryDbField.GetOrAdd(type, tp => new ConcurrentDictionary()).GetOrAdd(fieldName, fn => typeof(BaseRepository<,>).MakeGenericType(type, typeof(int)).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic)); public override IDbSet Set(Type entityType) @@ -33,10 +33,10 @@ public override IDbSet Set(Type entityType) { repo = Activator.CreateInstance(typeof(DefaultRepository<,>).MakeGenericType(entityType, typeof(int)), _repo.Orm); (repo as IBaseRepository).UnitOfWork = _repo.UnitOfWork; - GetRepositoryDbField(entityType, "_dbPriv").SetValue(repo, this); + GetRepositoryDbField(entityType, "_dbPriv").SetValue(repo, this); GetRepositoryDbField(entityType, "_asTablePriv").SetValue(repo, _repo.GetType().GetField("_asTablePriv", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_repo)); - //GetRepositoryDbField(_repo.EntityType, "_asTablePriv").GetValue(_repo)); + //GetRepositoryDbField(_repo.EntityType, "_asTablePriv").GetValue(_repo)); if (typeof(IBaseRepository<>).MakeGenericType(_repo.EntityType).IsAssignableFrom(_repo.GetType())) typeof(RepositoryDbContext).GetMethod("SetRepositoryDataFilter").MakeGenericMethod(_repo.EntityType) @@ -68,7 +68,8 @@ int SaveChangesSuccess() { UnitOfWork.EntityChangeReport.Report.AddRange(_entityChangeReport); if (UnitOfWork.EntityChangeReport.OnChange == null) UnitOfWork.EntityChangeReport.OnChange = Options.OnEntityChange; - } else + } + else EmitOnEntityChange(_entityChangeReport); } finally diff --git a/FreeSql.DbContext/Repository/DataFilter/DataFilterUtil.cs b/FreeSql.DbContext/Repository/DataFilter/DataFilterUtil.cs index ee5abb797..7c12663bc 100644 --- a/FreeSql.DbContext/Repository/DataFilter/DataFilterUtil.cs +++ b/FreeSql.DbContext/Repository/DataFilter/DataFilterUtil.cs @@ -13,8 +13,8 @@ internal class DataFilterUtil internal static Action _globalDataFilter; - static ConcurrentDictionary _dicSetRepositoryDataFilterApplyDataFilterFunc = new ConcurrentDictionary(); - static ConcurrentDictionary> _dicSetRepositoryDataFilterConvertFilterNotExists = new ConcurrentDictionary>(); + static ConcurrentDictionary _dicSetRepositoryDataFilterApplyDataFilterFunc = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem>(); + static ConcurrentDictionary> _dicSetRepositoryDataFilterConvertFilterNotExists = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem>>(); internal static void SetRepositoryDataFilter(object repos, Action scopedDataFilter) { if (scopedDataFilter != null) diff --git a/FreeSql.DbContext/UnitOfWork/UnitOfWork.cs b/FreeSql.DbContext/UnitOfWork/UnitOfWork.cs index b2a8d368c..6358afc74 100644 --- a/FreeSql.DbContext/UnitOfWork/UnitOfWork.cs +++ b/FreeSql.DbContext/UnitOfWork/UnitOfWork.cs @@ -15,7 +15,7 @@ public class UnitOfWork : IUnitOfWork /// /// 正在使用中的工作单元(调试) /// - public static ConcurrentDictionary DebugBeingUsed { get; } = new ConcurrentDictionary(); + public static ConcurrentDictionary DebugBeingUsed { get; } = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem>(); protected IFreeSql _fsql; protected Object _conn; diff --git a/FreeSql/DataAnnotations/TableAttribute.cs b/FreeSql/DataAnnotations/TableAttribute.cs index 683e48dcd..797bf7d7c 100644 --- a/FreeSql/DataAnnotations/TableAttribute.cs +++ b/FreeSql/DataAnnotations/TableAttribute.cs @@ -70,7 +70,7 @@ internal void ParseAsTable(TableInfo tb) tb.AsTableImpl = new DateTimeAsTableImpl(Name, DateTime.Parse(beginTime), (dt, idx) => { var atm6 = idx >= 0 && idx < intervals.Length ? intervals[idx] : intervals.Last(); - switch (atm7) + switch (atm7) { case "year": return dt.AddYears(atm6); case "month": return dt.AddMonths(atm6); @@ -86,30 +86,30 @@ internal void ParseAsTable(TableInfo tb) public interface IAsTable { string[] AllTables { get; } - IAsTable SetTableName(int index, string tableName); - string GetTableNameByColumnValue(object columnValue, bool autoExpand = false); + IAsTable SetTableName(int index, string tableName); + string GetTableNameByColumnValue(object columnValue, bool autoExpand = false); string[] GetTableNamesByColumnValueRange(object columnValue1, object columnValue2); - IAsTableTableNameRangeResult GetTableNamesBySqlWhere(string sqlWhere, List dbParams, SelectTableInfo tb, CommonUtils commonUtils); + IAsTableTableNameRangeResult GetTableNamesBySqlWhere(string sqlWhere, List dbParams, SelectTableInfo tb, CommonUtils commonUtils); IAsTable SetDefaultAllTables(Func audit); - } + } public class IAsTableTableNameRangeResult { public string[] Names { get; } public object ColumnValue1 { get; } public object ColumnValue2 { get; } public IAsTableTableNameRangeResult(string[] names, object columnValue1, object columnValue2) - { - Names = names; - ColumnValue1 = columnValue1; - ColumnValue2 = columnValue2; - } - } - class DateTimeAsTableImpl : IAsTable + { + Names = names; + ColumnValue1 = columnValue1; + ColumnValue2 = columnValue2; + } + } + class DateTimeAsTableImpl : IAsTable { readonly object _lock = new object(); readonly List _allTables = new List(); - readonly List _allTablesTime = new List(); - readonly DateTime _beginTime; + readonly List _allTablesTime = new List(); + readonly DateTime _beginTime; DateTime _lastTime; Func _nextTimeFunc; string _tableName; @@ -133,31 +133,31 @@ void ExpandTable(DateTime beginTime, DateTime endTime) { if (beginTime > endTime) endTime = _nextTimeFunc(beginTime, -1); lock (_lock) - { - var index = _allTables.Count; - while (beginTime <= endTime) + { + var index = _allTables.Count; + while (beginTime <= endTime) { var dtstr = beginTime.ToString(_tableNameFormat.Groups[1].Value); var name = _tableName.Replace(_tableNameFormat.Groups[0].Value, dtstr); if (_allTables.Contains(name)) throw new ArgumentException(CoreStrings.Generated_Same_SubTable(_tableName)); _allTables.Insert(0, name); - _allTablesTime.Insert(0, beginTime); - _lastTime = _nextTimeFunc(beginTime, index++); - beginTime = _lastTime; - } + _allTablesTime.Insert(0, beginTime); + _lastTime = _nextTimeFunc(beginTime, index++); + beginTime = _lastTime; + } } } public NativeTuple GetRangeByTableName(string tableName) { - lock (_lock) + lock (_lock) { var idx = _allTables.FindIndex(a => a == tableName); if (idx == -1) return null; - if (idx == 0) return NativeTuple.Create(_allTablesTime[idx], DateTime.Now); - if (idx == _allTables.Count - 1) return NativeTuple.Create(DateTime.MinValue, _allTablesTime[idx]); - return NativeTuple.Create(_allTablesTime[idx], _allTablesTime[idx - 1]); - } - } + if (idx == 0) return NativeTuple.Create(_allTablesTime[idx], DateTime.Now); + if (idx == _allTables.Count - 1) return NativeTuple.Create(DateTime.MinValue, _allTablesTime[idx]); + return NativeTuple.Create(_allTablesTime[idx], _allTablesTime[idx - 1]); + } + } DateTime ParseColumnValue(object columnValue) { if (columnValue == null) throw new Exception(CoreStrings.SubTableFieldValue_IsNotNull); @@ -236,7 +236,7 @@ public string[] GetTableNamesByColumnValueRange(object columnValue1, object colu } } - static readonly ConcurrentDictionary _dicRegSqlWhereDateTimes = new ConcurrentDictionary(); + static readonly ConcurrentDictionary _dicRegSqlWhereDateTimes = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); static Regex[] GetRegSqlWhereDateTimes(string columnName, string quoteParameterName) { return _dicRegSqlWhereDateTimes.GetOrAdd($"{columnName},{quoteParameterName}", cn => @@ -266,26 +266,26 @@ static Regex[] GetRegSqlWhereDateTimes(string columnName, string quoteParameterN Func _GetDefaultAllTables; public IAsTable SetDefaultAllTables(Func audit) { - _GetDefaultAllTables = audit; + _GetDefaultAllTables = audit; return this; } - /// - /// 可以匹配以下条件(支持参数化): - /// `field` BETWEEN '2022-01-01 00:00:00' AND '2022-03-01 00:00:00' - /// `field` > '2022-01-01 00:00:00' AND `field` < '2022-03-01 00:00:00' - /// `field` > '2022-01-01 00:00:00' AND `field` <= '2022-03-01 00:00:00' - /// `field` >= '2022-01-01 00:00:00' AND `field` < '2022-03-01 00:00:00' - /// `field` >= '2022-01-01 00:00:00' AND `field` <= '2022-03-01 00:00:00' - /// `field` > '2022-01-01 00:00:00' - /// `field` >= '2022-01-01 00:00:00' - /// `field` < '2022-01-01 00:00:00' - /// `field` <= '2022-01-01 00:00:00' - /// - /// - /// - public IAsTableTableNameRangeResult GetTableNamesBySqlWhere(string sqlWhere, List dbParams, SelectTableInfo tb, CommonUtils commonUtils) - { + /// + /// 可以匹配以下条件(支持参数化): + /// `field` BETWEEN '2022-01-01 00:00:00' AND '2022-03-01 00:00:00' + /// `field` > '2022-01-01 00:00:00' AND `field` < '2022-03-01 00:00:00' + /// `field` > '2022-01-01 00:00:00' AND `field` <= '2022-03-01 00:00:00' + /// `field` >= '2022-01-01 00:00:00' AND `field` < '2022-03-01 00:00:00' + /// `field` >= '2022-01-01 00:00:00' AND `field` <= '2022-03-01 00:00:00' + /// `field` > '2022-01-01 00:00:00' + /// `field` >= '2022-01-01 00:00:00' + /// `field` < '2022-01-01 00:00:00' + /// `field` <= '2022-01-01 00:00:00' + /// + /// + /// + public IAsTableTableNameRangeResult GetTableNamesBySqlWhere(string sqlWhere, List dbParams, SelectTableInfo tb, CommonUtils commonUtils) + { if (string.IsNullOrWhiteSpace(sqlWhere)) return new IAsTableTableNameRangeResult(_GetDefaultAllTables?.Invoke(AllTables) ?? AllTables, _beginTime, _lastTime); var quoteParameterName = ""; if (commonUtils._orm.Ado.DataType == DataType.ClickHouse) quoteParameterName = "@"; //特殊处理 Clickhouse 参数化 @@ -321,23 +321,23 @@ public IAsTableTableNameRangeResult GetTableNamesBySqlWhere(string sqlWhere, Lis var val1 = LocalGetParamValue(m.Groups[2].Value); var val2 = LocalGetParamValue(m.Groups[4].Value); if (val1 == null || val2 == null) throw new Exception(CoreStrings.Failed_SubTable_FieldValue(sqlWhere)); - return LocalGetTables(m.Groups[1].Value, m.Groups[3].Value, ParseColumnValue(val1), ParseColumnValue(val2)); + return LocalGetTables(m.Groups[1].Value, m.Groups[3].Value, ParseColumnValue(val1), ParseColumnValue(val2)); } m = regs[10].Match(newSqlWhere); if (m.Success) { var val1 = LocalGetParamValue(m.Groups[2].Value); if (val1 == null) throw new Exception(CoreStrings.Failed_SubTable_FieldValue(sqlWhere)); - return LocalGetTables2(m.Groups[1].Value, ParseColumnValue(val1)); + return LocalGetTables2(m.Groups[1].Value, ParseColumnValue(val1)); } return new IAsTableTableNameRangeResult(_GetDefaultAllTables?.Invoke(AllTables) ?? AllTables, _beginTime, _lastTime); - object LocalGetParamValue(string paramName) + object LocalGetParamValue(string paramName) { if (dictParams.TryGetValue(quoteParameterName + paramName, out var trydictVal)) return trydictVal; return dbParams.Where(a => a.ParameterName.Trim(quoteParameterNameCharArray) == paramName).FirstOrDefault()?.Value; } - IAsTableTableNameRangeResult LocalGetTables(string opt1, string opt2, DateTime val1, DateTime val2) + IAsTableTableNameRangeResult LocalGetTables(string opt1, string opt2, DateTime val1, DateTime val2) { switch (opt1) { @@ -351,12 +351,12 @@ IAsTableTableNameRangeResult LocalGetTables(string opt1, string opt2, DateTime v return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(_beginTime, val1 > val2 ? val2 : val1), _beginTime, val1 > val2 ? val2 : val1); case "<=": return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(_beginTime, val1 > val2 ? val2 : val1), _beginTime, val1 > val2 ? val2 : val1); - case ">": + case ">": val2 = val2.AddSeconds(1); return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(val2, val1), val2, val1); case ">=": return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(val2, val1), val2, val1); - } + } break; case ">": case ">=": @@ -368,17 +368,17 @@ IAsTableTableNameRangeResult LocalGetTables(string opt1, string opt2, DateTime v return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(val1, val2), val1, val2); case "<=": return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(val1, val2), val1, val2); - case ">": + case ">": val2 = val2.AddSeconds(1); return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(val1 > val2 ? val1 : val2, _lastTime), val1 > val2 ? val1 : val2, _lastTime); case ">=": return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(val1 > val2 ? val1 : val2, _lastTime), val1 > val2 ? val1 : val2, _lastTime); - } + } break; } return new IAsTableTableNameRangeResult(_GetDefaultAllTables?.Invoke(AllTables) ?? AllTables, _beginTime, _lastTime); - } - IAsTableTableNameRangeResult LocalGetTables2(string opt, DateTime val1) + } + IAsTableTableNameRangeResult LocalGetTables2(string opt, DateTime val1) { switch (m.Groups[1].Value) { @@ -387,16 +387,16 @@ IAsTableTableNameRangeResult LocalGetTables2(string opt, DateTime val1) case "<": val1 = val1.AddSeconds(-1); return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(_beginTime, val1), _beginTime, val1); - case "<=": + case "<=": return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(_beginTime, val1), _beginTime, val1); - case ">": + case ">": val1 = val1.AddSeconds(1); return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(val1, _lastTime), val1, _lastTime); - case ">=": + case ">=": return new IAsTableTableNameRangeResult(GetTableNamesByColumnValueRange(val1, _lastTime), val1, _lastTime); - } + } return new IAsTableTableNameRangeResult(_GetDefaultAllTables?.Invoke(AllTables) ?? AllTables, _beginTime, _lastTime); - } + } } public string[] AllTables @@ -409,14 +409,14 @@ public string[] AllTables } } } - public IAsTable SetTableName(int index, string tableName) + public IAsTable SetTableName(int index, string tableName) { - lock (_lock) - { + lock (_lock) + { index = _allTables.Count - 1 - index; _allTables[index] = tableName; - } + } return this; - } - } + } + } } diff --git a/FreeSql/Extensions/EntityUtilExtensions.cs b/FreeSql/Extensions/EntityUtilExtensions.cs index d4635e39b..2e80206e0 100644 --- a/FreeSql/Extensions/EntityUtilExtensions.cs +++ b/FreeSql/Extensions/EntityUtilExtensions.cs @@ -1,4 +1,5 @@ -using FreeSql.Internal.Model; +using FreeSql.Internal; +using FreeSql.Internal.Model; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -19,7 +20,8 @@ public static class EntityUtilExtensions static readonly MethodInfo MethodStringConcat = typeof(string).GetMethod("Concat", new Type[] { typeof(object) }); static readonly MethodInfo MethodFreeUtilNewMongodbId = typeof(FreeUtil).GetMethod("NewMongodbId"); - static ConcurrentDictionary>> _dicGetEntityKeyString = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicGetEntityKeyString + = Utils.GlobalCacheFactory.CreateCacheItem>>>(); /// /// 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 "" /// @@ -152,7 +154,7 @@ public static string GetEntityKeyString(this IFreeSql orm, Type entityType, obje }); return func(entity, genGuid); } - static ConcurrentDictionary>> _dicGetEntityKeyValues = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicGetEntityKeyValues = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); /// /// 获取实体的主键值,多个主键返回数组 /// @@ -193,7 +195,8 @@ public static object[] GetEntityKeyValues(this IFreeSql orm, Type entityType, ob }); return func(entity); } - static ConcurrentDictionary>>> _dicGetEntityValueWithPropertyName = new ConcurrentDictionary>>>(); + static ConcurrentDictionary>>> _dicGetEntityValueWithPropertyName + = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>>()); /// /// 获取实体的属性值 /// @@ -260,7 +263,7 @@ public static object GetPropertyValue(this TableInfo table, object entity, strin }); return func(entity); } - static ConcurrentDictionary>> _dicGetEntityString = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicGetEntityString = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); /// /// 获取实体的所有数据,以 (1, 2, xxx) 的形式 /// @@ -313,7 +316,7 @@ public static string GetEntityString(this IFreeSql orm, Type entityType, object /// /// 使用新实体的值,复盖旧实体的值 /// - static ConcurrentDictionary>> _dicMapEntityValue = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicMapEntityValue = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); public static void MapEntityValue(this IFreeSql orm, Type entityType, object entityFrom, object entityTo) { if (entityType == null) entityType = entityFrom?.GetType() ?? entityTo?.GetType(); @@ -355,7 +358,7 @@ public static void MapEntityValue(this IFreeSql orm, Type entityType, object ent func(entityFrom, entityTo); } - static ConcurrentDictionary>> _dicMapEntityKeyValue = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicMapEntityKeyValue = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); /// /// 使用新实体的主键值,复盖旧实体的主键值 /// @@ -388,7 +391,7 @@ public static void MapEntityKeyValue(this IFreeSql orm, Type entityType, object func(entityFrom, entityTo); } - static ConcurrentDictionary>> _dicSetEntityIdentityValueWithPrimary = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicSetEntityIdentityValueWithPrimary = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); /// /// 设置实体中主键内的自增字段值(若存在) /// @@ -424,7 +427,7 @@ public static void SetEntityIdentityValueWithPrimary(this IFreeSql orm, Type ent }); func(entity, idtval); } - static ConcurrentDictionary>> _dicGetEntityIdentityValueWithPrimary = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicGetEntityIdentityValueWithPrimary = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); /// /// 获取实体中主键内的自增字段值(若存在) /// @@ -473,7 +476,7 @@ public static long GetEntityIdentityValueWithPrimary(this IFreeSql orm, Type ent return func(entity); } - static ConcurrentDictionary>> _dicClearEntityPrimaryValueWithIdentityAndGuid = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicClearEntityPrimaryValueWithIdentityAndGuid = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); /// /// 清除实体的主键值,将自增、Guid类型的主键值清除 /// @@ -521,7 +524,7 @@ public static void ClearEntityPrimaryValueWithIdentityAndGuid(this IFreeSql orm, func(entity); } - static ConcurrentDictionary>> _dicClearEntityPrimaryValueWithIdentity = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicClearEntityPrimaryValueWithIdentity = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); /// /// 清除实体的主键值,将自增、Guid类型的主键值清除 /// @@ -558,7 +561,7 @@ public static void ClearEntityPrimaryValueWithIdentity(this IFreeSql orm, Type e func(entity); } - static ConcurrentDictionary>> _dicCompareEntityValueReturnColumns = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicCompareEntityValueReturnColumns = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); /// /// 对比两个实体值,返回相同/或不相同的列名 /// @@ -625,7 +628,8 @@ public static string[] CompareEntityValueReturnColumns(this IFreeSql orm, Type e }); var result = func(entity1, entity2, isEqual); var tmptb = orm.CodeFirst.GetTableByEntity(entityType); - if (tmptb.ColumnsByCanUpdateDbUpdateValue.Length > 0) { + if (tmptb.ColumnsByCanUpdateDbUpdateValue.Length > 0) + { if (isEqual && result.Length + tmptb.ColumnsByCanUpdateDbUpdateValue.Length == tmptb.ColumnsByCs.Count) return result.Concat(tmptb.ColumnsByCanUpdateDbUpdateValue.Select(a => a.Attribute.Name)).ToArray(); if (!isEqual && result.Length == tmptb.ColumnsByCanUpdateDbUpdateValue.Length) @@ -634,7 +638,7 @@ public static string[] CompareEntityValueReturnColumns(this IFreeSql orm, Type e return result; } - static ConcurrentDictionary>> _dicSetEntityIncrByWithPropertyName = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicSetEntityIncrByWithPropertyName = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); /// /// 设置实体中某属性的数值增加指定的值 /// @@ -678,7 +682,7 @@ public static void SetEntityIncrByWithPropertyName(this IFreeSql orm, Type entit func(entity, propertyName, incrBy); } - static ConcurrentDictionary>>> _dicSetEntityValueWithPropertyName = new ConcurrentDictionary>>>(); + static ConcurrentDictionary>>> _dicSetEntityValueWithPropertyName = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>>()); /// /// 设置实体中某属性的值 /// @@ -785,8 +789,8 @@ public static void SetPropertyValue(this TableInfo table, object entity, string func(entity, propertyName, value); } - static ConcurrentDictionary _dicAppendEntityUpdateSetWithColumnMethods = new ConcurrentDictionary(); - static ConcurrentDictionary> _dicAppendEntityUpdateSetWithColumnMethod = new ConcurrentDictionary>(); + static ConcurrentDictionary _dicAppendEntityUpdateSetWithColumnMethods = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); + static ConcurrentDictionary> _dicAppendEntityUpdateSetWithColumnMethod = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); /// /// 缓存执行 IUpdate.Set /// diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs index 0a2e12961..9078e7195 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs @@ -182,7 +182,7 @@ internal static NewExpression InternalNewExpression(this Type that) return Expression.New(ctor, ctor.GetParameters().Select(a => Expression.Constant(a.ParameterType.CreateInstanceGetDefaultValue(), a.ParameterType))); } - static ConcurrentDictionary> _dicInternalGetTypeConstructor0OrFirst = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicInternalGetTypeConstructor0OrFirst = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); internal static ConstructorInfo InternalGetTypeConstructor0OrFirst(this Type that, bool isThrow = true) { var ret = _dicInternalGetTypeConstructor0OrFirst.GetOrAdd(that, tp => @@ -197,7 +197,7 @@ internal static ConstructorInfo InternalGetTypeConstructor0OrFirst(this Type tha return ret.Value; } - static ConcurrentDictionary> _dicGetPropertiesDictIgnoreCase = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicGetPropertiesDictIgnoreCase = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); public static Dictionary GetPropertiesDictIgnoreCase(this Type that) => that == null ? null : _dicGetPropertiesDictIgnoreCase.GetOrAdd(that, tp => { var props = that.GetProperties().GroupBy(p => p.DeclaringType).Reverse().SelectMany(p => p); //将基类的属性位置放在前面 #164 @@ -232,7 +232,7 @@ public static double Distance(this Point that, Point point) } #region Enum 对象扩展方法 - static ConcurrentDictionary _dicGetFields = new ConcurrentDictionary(); + static ConcurrentDictionary _dicGetFields = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); public static object GetEnum(this IDataReader dr, int index) { var value = dr.GetString(index); @@ -613,7 +613,7 @@ async public static Task> ToTreeListAsync(this ISelect that, Ca #endregion #region AsTreeCte(..) 递归查询 - static ConcurrentDictionary _dicMySqlVersion = new ConcurrentDictionary(); + static ConcurrentDictionary _dicMySqlVersion = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); /// /// 使用递归 CTE 查询树型的所有子记录,或者所有父记录。 /// 通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、Firebird、达梦、人大金仓、翰高 @@ -751,7 +751,7 @@ WHERE @cte_ids IS NOT NULL case DataType.CustomSqlServer: case DataType.Firebird: case DataType.ClickHouse: - sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, select._tableRule, + sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, select._tableRule, Expression.Call(typeof(Convert).GetMethod("ToString", new Type[] { typeof(string) }), pathSelector?.Body), select._diymemexpWithTempQuery, null, null); break; case DataType.MySql: diff --git a/FreeSql/Extensions/LambadaExpressionExtensions.cs b/FreeSql/Extensions/LambadaExpressionExtensions.cs index 9f2191948..41743ccfd 100644 --- a/FreeSql/Extensions/LambadaExpressionExtensions.cs +++ b/FreeSql/Extensions/LambadaExpressionExtensions.cs @@ -240,7 +240,6 @@ public static ParameterExpression GetParameter(this Expression exp) return test.Result; } - static ConcurrentDictionary> _dicTypeMethod = new ConcurrentDictionary>(); public static bool IsStringJoin(this MethodCallExpression exp, out Expression tolistObjectExpOut, out MethodInfo toListMethodOut, out LambdaExpression toListArgs0Out) { if (exp.Arguments.Count == 2 && diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 5f6a3f2a1..5c951ecc1 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1104,93 +1104,6 @@ - - - 动态创建实体类型 - - - - - 配置Class - - 类名 - 类标记的特性[Table(Name = "xxx")] [Index(xxxx)] - - - - - 获取类型构建器,可作为要构建的Type来引用 - - - - - 配置属性 - - 属性名称 - 属性类型 - 属性标记的特性-支持多个 - - - - - 配置属性 - - 属性名称 - 属性类型 - 该属性是否重写父类属性 - 属性标记的特性-支持多个 - - - - - 配置属性 - - 属性名称 - 属性类型 - 该属性是否重写父类属性 - 属性默认值 - 属性标记的特性-支持多个 - - - - - 配置父类 - - 父类类型 - - - - - Override属性 - - - - - - Emit动态创建出Class - Type - - - - - - Emit动态创建出Class - Type,不附带获取TableInfo - - - - - - 首字母小写 - - - - - - - 首字母大写 - - - - 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 "" @@ -1484,6 +1397,13 @@ + + + 解决多实例下相同类型映射到不同表的问题,可以覆盖为从自定义缓存中构建 + + 自定义缓存策略,参考 + + 使用原始连接池(ado.net、odbc、oledb) @@ -5081,11 +5001,6 @@ - - - 用于解决多实例情况下的静态集合缓存问题 - - @@ -5908,28 +5823,6 @@ 请使用 fsql.InsertDict(dict) 方法插入字典数据 - - - 动态构建Class Type - - - - - - 根据字典,创建 table 对应的实体对象 - - - - - - - - 根据实体对象,创建 table 对应的字典 - - - - - C#: that >= between && that <= and @@ -6446,3 +6339,127 @@ + + + + + + + 插入数据,传入实体集合 + + + + + + + + 插入数据,传入实体集合 + + + + + + + + 插入或更新数据,此功能依赖数据库特性(低版本可能不支持),参考如下: + MySql 5.6+: on duplicate key update + PostgreSQL 9.4+: on conflict do update + SqlServer 2008+: merge into + Oracle 11+: merge into + Sqlite: replace into + 达梦: merge into + 人大金仓:on conflict do update + 神通:merge into + MsAccess:不支持 + 注意区别:FreeSql.Repository 仓储也有 InsertOrUpdate 方法(不依赖数据库特性) + + + + + + + 修改数据 + + + + + + + 修改数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} + + + 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 + + + + + 查询数据 + + + + + + + 查询数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} + + + 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 + + + + + 删除数据 + + + + + + + 删除数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} + + + 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 + + + + + 开启事务(不支持异步) + v1.5.0 关闭了线程事务超时自动提交的机制 + + 事务体 () => {} + + + + 开启事务(不支持异步) + v1.5.0 关闭了线程事务超时自动提交的机制 + + + 事务体 () => {} + + + + 数据库访问对象 + + + + + 所有拦截方法都在这里 + + + + + CodeFirst 模式开发相关方法 + + + + + DbFirst 模式开发相关方法 + + + + + 全局过滤设置,可默认附加为 Select/Update/Delete 条件 + + + + diff --git a/FreeSql/FreeSqlBuilder.cs b/FreeSql/FreeSqlBuilder.cs index e3ff2c429..04393576e 100644 --- a/FreeSql/FreeSqlBuilder.cs +++ b/FreeSql/FreeSqlBuilder.cs @@ -12,6 +12,7 @@ using FreeSql.Internal.Model.Interface; using System.Threading; using FreeSql.Internal.Model; +using FreeSql.Interface; namespace FreeSql { @@ -58,9 +59,21 @@ public FreeSqlBuilder UseConnectionString(DataType dataType, string connectionSt /// /// /// + [Obsolete("请使用 UseCacheFactory", true)] public FreeSqlBuilder UseCustomTableEntityCacheFactory(Func>> factory) { - Utils.ChacheTableEntityFactory = factory; + Utils._cacheGetTableByEntity = factory.Invoke(); + return this; + } + + /// + /// 解决多实例下相同类型映射到不同表的问题,可以覆盖为从自定义缓存中构建 + /// + /// 自定义缓存策略,参考 + /// + public FreeSqlBuilder UseCacheFactory(IGlobalCacheFactory cacheFactory) + { + Utils.GlobalCacheFactory = cacheFactory; return this; } /// @@ -646,7 +659,7 @@ public IFreeSql Build() return ret; } static int _isTypeHandlered = 0; - ConcurrentDictionary _dicTypeHandlerTypes = new ConcurrentDictionary(); + ConcurrentDictionary _dicTypeHandlerTypes = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); object _concurrentObj = new object(); } } diff --git a/FreeSql/Interface/IGlobalCacheFactory.cs b/FreeSql/Interface/IGlobalCacheFactory.cs new file mode 100644 index 000000000..b42e563ef --- /dev/null +++ b/FreeSql/Interface/IGlobalCacheFactory.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Text; + +namespace FreeSql.Interface +{ + public interface IGlobalCacheFactory + { + T CreateCacheItem(T defaultValue = null) where T : class, new(); + T CreateCacheItem() where T : new(); + } +} diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 385406315..7682fa993 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -726,7 +726,7 @@ public string ExpressionWhereLambda(List _tables, Func dicRegexAlias = new ConcurrentDictionary(); + static ConcurrentDictionary dicRegexAlias = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); public void ExpressionJoinLambda(List _tables, Func _tableRule, SelectTableInfoType tbtype, Expression exp, BaseDiyMemberExpression diymemexp, List whereGlobalFilter) { var tbidx = _tables.Count; @@ -759,12 +759,12 @@ public void ExpressionJoinLambda(List _tables, Func _dicExpressionLambdaToSqlAsSelectMethodInfo = new ConcurrentDictionary(); - static ConcurrentDictionary _dicExpressionLambdaToSqlAsSelectWhereMethodInfo = new ConcurrentDictionary(); - static ConcurrentDictionary _dicExpressionLambdaToSqlAsSelectWhereSqlMethodInfo = new ConcurrentDictionary(); - static ConcurrentDictionary> _dicExpressionLambdaToSqlAsSelectAggMethodInfo = new ConcurrentDictionary>(); - internal static ConcurrentDictionary _dicNullableValueProperty = new ConcurrentDictionary(); - static ConcurrentDictionary _dicFreeSqlGlobalExtensionsAsSelectExpression = new ConcurrentDictionary(); + static ConcurrentDictionary _dicExpressionLambdaToSqlAsSelectMethodInfo = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); + static ConcurrentDictionary _dicExpressionLambdaToSqlAsSelectWhereMethodInfo = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); + static ConcurrentDictionary _dicExpressionLambdaToSqlAsSelectWhereSqlMethodInfo = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); + static ConcurrentDictionary> _dicExpressionLambdaToSqlAsSelectAggMethodInfo = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); + internal static ConcurrentDictionary _dicNullableValueProperty = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); + static ConcurrentDictionary _dicFreeSqlGlobalExtensionsAsSelectExpression = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); static MethodInfo MethodDateTimeSubtractDateTime = typeof(DateTime).GetMethod("Subtract", new Type[] { typeof(DateTime) }); static MethodInfo MethodDateTimeSubtractTimeSpan = typeof(DateTime).GetMethod("Subtract", new Type[] { typeof(TimeSpan) }); static MethodInfo MethodMathFloor = typeof(Math).GetMethod("Floor", new Type[] { typeof(double) }); @@ -962,11 +962,11 @@ rightExp is UnaryExpression rightExpUexp && tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); return $"{left} {oper} {right}"; } - static ConcurrentDictionary _dicTypeExistsExpressionCallAttribute = new ConcurrentDictionary(); - static ConcurrentDictionary> _dicMethodExistsExpressionCallAttribute = new ConcurrentDictionary>(); - static ConcurrentDictionary _dicTypeExpressionCallClassContextFields = new ConcurrentDictionary(); - static ThreadLocal> _subSelectParentDiyMemExps = new ThreadLocal>(); //子查询的所有父自定义查询,比如分组之后的子查询 - static ConcurrentDictionary _dicSelectMethodToSql = new ConcurrentDictionary(); + static ConcurrentDictionary _dicTypeExistsExpressionCallAttribute = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); + static ConcurrentDictionary> _dicMethodExistsExpressionCallAttribute = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); + static ConcurrentDictionary _dicTypeExpressionCallClassContextFields = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); + static ThreadLocal> _subSelectParentDiyMemExps = Utils.GlobalCacheFactory.CreateCacheItem>>(); //子查询的所有父自定义查询,比如分组之后的子查询 + static ConcurrentDictionary _dicSelectMethodToSql = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); public string ExpressionLambdaToSql(Expression exp, ExpTSC tsc) { if (exp == null) return ""; @@ -2403,7 +2403,7 @@ public ExpTSC CloneDisableDiyParse() } } - static ConcurrentDictionary> _dicGetWhereCascadeSqlError = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicGetWhereCascadeSqlError = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); public string GetWhereCascadeSql(SelectTableInfo tb, IEnumerable filters, bool isMultitb) { if (filters.Any()) diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderTransaction.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderTransaction.cs index e87abc329..77607fae6 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderTransaction.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderTransaction.cs @@ -30,7 +30,7 @@ public Transaction2(Object conn, DbTransaction tran, TimeSpan time } } - private ConcurrentDictionary _trans = new ConcurrentDictionary(); + private ConcurrentDictionary _trans = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); public DbTransaction TransactionCurrentThread => _trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var conn) && conn.Transaction?.Connection != null ? conn.Transaction : null; public Aop.TraceBeforeEventArgs TransactionCurrentThreadAopBefore => _trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var conn) && conn.Transaction?.Connection != null ? conn.AopBefore : null; diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs index 8f406200c..a4e5e47d3 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs @@ -35,7 +35,7 @@ public string Addslashes(string filter, params object[] parms) } try { string ret = string.Format(CultureInfo.InvariantCulture, filter, nparms); return ret; } catch { return filter; } } - static ConcurrentDictionary _dicAddslashesReplaceIsNull = new ConcurrentDictionary(); + static ConcurrentDictionary _dicAddslashesReplaceIsNull = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); protected string AddslashesIEnumerable(object param, Type mapType, ColumnInfo mapColumn) { diff --git a/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs b/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs index f6ba92946..7f1820a49 100644 --- a/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs +++ b/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs @@ -51,13 +51,13 @@ protected string GetTableNameLowerOrUpper(string tableName) } public string GetComparisonDDLStatements() => this.GetComparisonDDLStatements(new TypeSchemaAndName(GetTableByEntity(typeof(TEntity)), "")); - public string GetComparisonDDLStatements(params Type[] entityTypes) => entityTypes == null ? null : + public string GetComparisonDDLStatements(params Type[] entityTypes) => entityTypes == null ? null : this.GetComparisonDDLStatements(entityTypes.Distinct().Select(a => new TypeSchemaAndName(GetTableByEntity(a), "")).ToArray()); public string GetComparisonDDLStatements(Type entityType, string tableName) => this.GetComparisonDDLStatements(new TypeSchemaAndName(GetTableByEntity(entityType), GetTableNameLowerOrUpper(tableName))); - public string GetComparisonDDLStatements(TableInfo tableSchema, string tableName) => - this.GetComparisonDDLStatements(new TypeSchemaAndName(tableSchema, GetTableNameLowerOrUpper(tableName))); - protected abstract string GetComparisonDDLStatements(params TypeSchemaAndName[] objects); + public string GetComparisonDDLStatements(TableInfo tableSchema, string tableName) => + this.GetComparisonDDLStatements(new TypeSchemaAndName(tableSchema, GetTableNameLowerOrUpper(tableName))); + protected abstract string GetComparisonDDLStatements(params TypeSchemaAndName[] objects); public class TypeSchemaAndName { public TableInfo tableSchema { get; } @@ -71,7 +71,7 @@ public TypeSchemaAndName(TableInfo tableSchema, string tableName) static object syncStructureLock = new object(); object _dicSycedLock = new object(); - public ConcurrentDictionary> _dicSynced = new ConcurrentDictionary>(); + public ConcurrentDictionary> _dicSynced = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); internal ConcurrentDictionary _dicSycedGetOrAdd(Type entityType) { if (_dicSynced.TryGetValue(entityType, out var trydic) == false) @@ -85,26 +85,26 @@ public void _dicSycedTryAdd(Type entityType, string tableName = null) => public void SyncStructure() => this.SyncStructure(new TypeSchemaAndName(GetTableByEntity(typeof(TEntity)), "")); - public void SyncStructure(params Type[] entityTypes) => + public void SyncStructure(params Type[] entityTypes) => this.SyncStructure(entityTypes?.Distinct().Select(a => new TypeSchemaAndName(GetTableByEntity(a), "")).ToArray()); public void SyncStructure(Type entityType, string tableName, bool isForceSync) => this.SyncStructure(GetTableByEntity(entityType), tableName, isForceSync); - public void SyncStructure(TableInfo tableSchema, string tableName, bool isForceSync = false) + public void SyncStructure(TableInfo tableSchema, string tableName, bool isForceSync = false) { tableName = GetTableNameLowerOrUpper(tableName); - if (isForceSync && tableSchema?.Type != null && _dicSynced.TryGetValue(tableSchema.Type, out var dic)) dic.TryRemove(tableName, out var old); - this.SyncStructure(new TypeSchemaAndName(tableSchema, tableName)); - } + if (isForceSync && tableSchema?.Type != null && _dicSynced.TryGetValue(tableSchema.Type, out var dic)) dic.TryRemove(tableName, out var old); + this.SyncStructure(new TypeSchemaAndName(tableSchema, tableName)); + } protected void SyncStructure(params TypeSchemaAndName[] objects) { if (objects == null) return; var syncObjects = objects.Where(a => a.tableSchema?.Type != null && ( - a.tableSchema.Type == typeof(object) && a.tableSchema.Columns.Any() - || + a.tableSchema.Type == typeof(object) && a.tableSchema.Columns.Any() + || a.tableSchema.Type != typeof(object) && _dicSycedGetOrAdd(a.tableSchema.Type).ContainsKey(GetTableNameLowerOrUpper(a.tableName)) == false - ) && + ) && a.tableSchema?.DisableSyncStructure == false) .Select(a => new TypeSchemaAndName(a.tableSchema, GetTableNameLowerOrUpper(a.tableName))) .Where(a => !(string.IsNullOrEmpty(a.tableName) == true && a.tableSchema?.AsTableImpl != null)) diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index a922b2791..5b544aa91 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -360,7 +360,7 @@ public Expression ConvertStringPropertyToExpression(string property, bool fromFi public static MethodInfo MethodStringContains = typeof(string).GetMethod("Contains", new[] { typeof(string) }); public static MethodInfo MethodStringStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) }); public static MethodInfo MethodStringEndsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string) }); - static ConcurrentDictionary MethodEnumerableDic = new ConcurrentDictionary(); + static ConcurrentDictionary MethodEnumerableDic = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); public static MethodInfo GetMethodEnumerable(string methodName) => MethodEnumerableDic.GetOrAdd(methodName, et => { var methods = typeof(Enumerable).GetMethods().Where(a => a.Name == et); @@ -1237,7 +1237,7 @@ bool IsIgnoreFilter(DynamicFilterInfo testFilter) string.IsNullOrEmpty(testFilter.Value?.ToString()); } } - static ConcurrentDictionary _dicMethodIsDynamicFilterCustomAttribute = new ConcurrentDictionary(); + static ConcurrentDictionary _dicMethodIsDynamicFilterCustomAttribute = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); static bool MethodIsDynamicFilterCustomAttribute(MethodInfo method) => _dicMethodIsDynamicFilterCustomAttribute.GetOrAdd(method, m => { object[] attrs = null; diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs index be40ee340..9cef09f50 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs @@ -395,7 +395,7 @@ internal List ToListMapReaderPrivate(ReadAnonymousTypeAfInfo a return ToListMrPrivate(sql, af, otherData); } protected List ToListMapReader(ReadAnonymousTypeAfInfo af) => ToListMapReaderPrivate(af, null); - static ConcurrentDictionary _dicGetAllFieldExpressionTree = new ConcurrentDictionary(); + static ConcurrentDictionary _dicGetAllFieldExpressionTree = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); public class GetAllFieldExpressionTreeInfo { public string Field { get; set; } @@ -760,7 +760,7 @@ public GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevel2(bool isRere Expression.Call(retExp, propGetSetMethod, drvalExp), Expression.Catch(typeof(Exception), Expression.Call(retExp, propGetSetMethod, Expression.Convert(drvalExpCatch, col.CsType)) - //Expression.Throw(Expression.Constant(new Exception($"{_commonUtils.QuoteSqlName(col.Attribute.Name)} is NULL,除非设置特性 [Column(IsNullable = false)]"))) + //Expression.Throw(Expression.Constant(new Exception($"{_commonUtils.QuoteSqlName(col.Attribute.Name)} is NULL,除非设置特性 [Column(IsNullable = false)]"))) ))); } else @@ -769,7 +769,7 @@ public GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevel2(bool isRere Expression.Call(retExp, propGetSetMethod, drvalExp), Expression.Catch(typeof(Exception), Expression.Call(retExp, propGetSetMethod, Expression.Default(col.CsType)) - //Expression.Throw(Expression.Constant(new Exception($"{_commonUtils.QuoteSqlName(col.Attribute.Name)} is NULL,除非设置特性 [Column(IsNullable = false)]"))) + //Expression.Throw(Expression.Constant(new Exception($"{_commonUtils.QuoteSqlName(col.Attribute.Name)} is NULL,除非设置特性 [Column(IsNullable = false)]"))) ))); } } @@ -1001,7 +1001,7 @@ protected string InternalGetInsertIntoToSql(string tableName, Exp var index = -10000; //临时规则,不返回 as1 _commonExpression.ReadAnonymousField(_tables, _tableRule, field, map, ref index, select, null, _diymemexpWithTempQuery, _whereGlobalFilter, null, null, false); //不走 DTO 映射,不处理 IncludeMany - + var childs = map.Childs; if (childs.Any() == false) throw new ArgumentException(CoreStrings.InsertInto_No_Property_Selected(typeof(TTargetEntity).DisplayCsharp())); foreach (var col in tb.Columns.Values) @@ -1388,7 +1388,7 @@ async protected Task InternalSumAsync(Expression exp, CancellationToken return (await ToListQfPrivateAsync(sql, field, cancellationToken)).Sum(); } - static ConcurrentDictionary _dicGetMethodsByName = new ConcurrentDictionary(); + static ConcurrentDictionary _dicGetMethodsByName = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); async protected Task> InternalToListAsync(Expression select, CancellationToken cancellationToken) { //【注意】:此异步有特别逻辑,因为要处理子查询集合 ToList -> ToListAsync,原因是 LambdaExpression 表达式树内不支持 await Async @@ -1449,7 +1449,8 @@ async protected Task> InternalToListAsync(Expression sele return newexpParm; }).ToArray(); var newexpCallExp = (newexp as MethodCallExpression); - if (newexpCallExp?.Object != null) { + if (newexpCallExp?.Object != null) + { var asyncMethods = _dicGetMethodsByName.GetOrAdd(newexpCallExp.Object.Type, dgmbn => dgmbn.GetMethods().Where(c => c.Name == $"{newexpCallExp.Method.Name}Async") .Concat(dgmbn.GetInterfaces().SelectMany(b => b.GetMethods().Where(c => c.Name == $"{newexpCallExp.Method.Name}Async"))).ToArray()); var asyncMethod = asyncMethods.Length == 1 ? asyncMethods.First() : null; diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index 5b02908a9..0ab31ae4c 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -693,7 +693,7 @@ static NativeTuple> GetExpressionSta return NativeTuple.Create(param, members.ToList()); } static MethodInfo GetEntityValueWithPropertyNameMethod = typeof(EntityUtilExtensions).GetMethod("GetEntityValueWithPropertyName"); - static ConcurrentDictionary> _dicTypeMethod = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicTypeMethod = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); public ISelect IncludeMany(Expression>> navigateSelector, Action> then = null) where TNavigate : class { var throwNavigateSelector = new Exception(CoreStrings.IncludeMany_ParameterType_Error_Use_MemberAccess); diff --git a/FreeSql/Internal/CommonUtils.cs b/FreeSql/Internal/CommonUtils.cs index 1ceea9384..f9a7c675f 100644 --- a/FreeSql/Internal/CommonUtils.cs +++ b/FreeSql/Internal/CommonUtils.cs @@ -28,7 +28,8 @@ public abstract class CommonUtils public abstract string FormatSql(string sql, params object[] args); public bool IsQuoteSqlName = true; - public string QuoteSqlName(params string[] name) { + public string QuoteSqlName(params string[] name) + { if (IsQuoteSqlName) return QuoteSqlNameAdapter(name); if (name == null) return ""; return string.Join(".", name); @@ -40,10 +41,10 @@ public static string[] GetSplitTableNames(string name, char leftQuote, char righ { if (string.IsNullOrEmpty(name)) return null; if (name.IndexOf(leftQuote) == -1) return name.Split(new[] { '.' }, size); - name = Regex.Replace(name, - (leftQuote == '[' ? "\\" : "") + + name = Regex.Replace(name, + (leftQuote == '[' ? "\\" : "") + leftQuote + @"([^" + (rightQuote == ']' ? "\\" : "") + rightQuote + @"]+)" + - (rightQuote == ']' ? "\\" : "") + + (rightQuote == ']' ? "\\" : "") + rightQuote, m => m.Groups[1].Value.Replace('.', '?')); var ret = name.Split(new[] { '.' }, size); for (var a = 0; a < ret.Length; a++) @@ -109,7 +110,7 @@ public CommonUtils(IFreeSql orm) _orm = orm; } - ConcurrentDictionary dicConfigEntity = new ConcurrentDictionary(); + ConcurrentDictionary dicConfigEntity = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); public ICodeFirst ConfigEntity(Action> entity) { if (entity == null) return _orm.CodeFirst; @@ -135,7 +136,7 @@ public TableAttribute GetConfigEntity(Type type) } public MappingPriorityType[] _mappingPriorityTypes = new[] { MappingPriorityType.Aop, MappingPriorityType.FluentApi, MappingPriorityType.Attribute }; - ConcurrentDictionary> dicAopConfigEntityIndex = new ConcurrentDictionary>(); + ConcurrentDictionary> dicAopConfigEntityIndex = Utils.GlobalCacheFactory.CreateCacheItem>>(); public TableAttribute GetEntityTableAttribute(Type type) { var attr = new TableAttribute(); @@ -156,7 +157,7 @@ public TableAttribute GetEntityTableAttribute(Type type) AsTable = attr.AsTable } }; - _orm.Aop.ConfigEntityHandler(_orm, aope); + _orm.Aop.ConfigEntityHandler(_orm, aope); var tryattr = aope.ModifyResult; if (!string.IsNullOrEmpty(tryattr.Name) && tryattr.Name != type.Name) attr.Name = tryattr.Name; if (!string.IsNullOrEmpty(tryattr.OldName)) attr.OldName = tryattr.OldName; @@ -618,7 +619,8 @@ public static Dictionary GetPropertyCommentByDescriptionAttribut string GetByAttribute(object[] attrs, string attributeName) { - var dyattr = attrs?.Where(a => { + var dyattr = attrs?.Where(a => + { return ((a as Attribute)?.TypeId as Type)?.Name == attributeName; }).FirstOrDefault(); if (dyattr == null) return null; @@ -636,8 +638,8 @@ void GetDydesc(PropertyInfo prop) object[] attrs = null; try { - attrs = prop == null ? - type.GetCustomAttributes(false).ToArray() : + attrs = prop == null ? + type.GetCustomAttributes(false).ToArray() : prop.GetCustomAttributes(false).ToArray(); //.net core 反射存在版本冲突问题,导致该方法异常 } catch { } diff --git a/FreeSql/Internal/DefaultCacheFactory.cs b/FreeSql/Internal/DefaultCacheFactory.cs new file mode 100644 index 000000000..71bd26828 --- /dev/null +++ b/FreeSql/Internal/DefaultCacheFactory.cs @@ -0,0 +1,21 @@ +using FreeSql.Interface; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Text; + +namespace FreeSql.Internal +{ + public class DefaultCacheFactory : IGlobalCacheFactory + { + public T CreateCacheItem(T defaultValue = null) where T : class, new() + { + return defaultValue ?? new T(); + } + + public T CreateCacheItem() where T : new() + { + return new T(); + } + } +} diff --git a/FreeSql/Internal/Model/ColumnInfo.cs b/FreeSql/Internal/Model/ColumnInfo.cs index 98c5ed908..2df359cd9 100644 --- a/FreeSql/Internal/Model/ColumnInfo.cs +++ b/FreeSql/Internal/Model/ColumnInfo.cs @@ -65,7 +65,7 @@ public void SetValue(object obj, object val) - static ConcurrentDictionary> _dicGetMapValue = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicGetMapValue = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); [Obsolete("请使用 GetDbValue 或者 GetValue")] public object GetMapValue(object obj) { @@ -101,7 +101,7 @@ public object GetMapValue(object obj) }); return func(obj); } - static ConcurrentDictionary> _dicSetMapValue = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicSetMapValue = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); [Obsolete("请使用 SetValue")] public void SetMapValue(object obj, object val) { diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index fe755cc38..950779a35 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -1,4 +1,5 @@ using FreeSql.DataAnnotations; +using FreeSql.Interface; using FreeSql.Internal.Model; using FreeSql.Internal.Model.Interface; using System; @@ -19,12 +20,9 @@ namespace FreeSql.Internal { public class Utils { - /// - /// 用于解决多实例情况下的静态集合缓存问题 - /// - public static Func>> ChacheTableEntityFactory = null; - private static ConcurrentDictionary> __cacheGetTableByEntity = new ConcurrentDictionary>(); - public static ConcurrentDictionary> _cacheGetTableByEntity => ChacheTableEntityFactory?.Invoke() ?? __cacheGetTableByEntity; + public static IGlobalCacheFactory GlobalCacheFactory { get; set; } = new DefaultCacheFactory(); + + public static ConcurrentDictionary> _cacheGetTableByEntity = GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); internal static void RemoveTableByEntity(Type entity, CommonUtils common) { if (entity.IsAnonymousType() || @@ -129,20 +127,20 @@ internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) if (tp == null && colattr != null) colattr.IsIgnore = true; //无法匹配的属性,认定是导航属性,且自动过滤 var col = ColumnAttributeToInfo(trytb, entityDefault, p.Name, p.PropertyType, setMethod == null, ref colattr, tp, common); - if (col == null) continue; + if (col == null) continue; - if (propsComment != null && propsComment.TryGetValue(p.Name, out var trycomment)) - col.Comment = trycomment; - if (string.IsNullOrEmpty(col.Comment) && propsCommentByDescAttr != null && propsCommentByDescAttr.TryGetValue(p.Name, out trycomment)) - col.Comment = trycomment; + if (propsComment != null && propsComment.TryGetValue(p.Name, out var trycomment)) + col.Comment = trycomment; + if (string.IsNullOrEmpty(col.Comment) && propsCommentByDescAttr != null && propsCommentByDescAttr.TryGetValue(p.Name, out trycomment)) + col.Comment = trycomment; - trytb.Columns.Add(colattr.Name, col); + trytb.Columns.Add(colattr.Name, col); trytb.ColumnsByCs.Add(p.Name, col); columnsList.Add(col); } var indexes = common.GetEntityIndexAttribute(trytb.Type); - AuditTableInfo(trytb, tbattr, indexes, columnsList, common); + AuditTableInfo(trytb, tbattr, indexes, columnsList, common); tbc.AddOrUpdate(entity, trytb, (oldkey, oldval) => trytb); #region 查找导航属性的关系、virtual 属性延时加载,动态产生新的重写类 @@ -197,70 +195,70 @@ internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) } public static ColumnInfo ColumnAttributeToInfo(TableInfo trytb, object entityDefault, string csName, Type mapType, bool isIgnore, ref ColumnAttribute colattr, DbInfoResult tp, CommonUtils common) { - var colattrIsNullable = colattr?._IsNullable; - var colattrIsNull = colattr == null; - if (colattr == null) - colattr = new ColumnAttribute - { - Name = csName, - DbType = tp.dbtypeFull, - IsNullable = tp.isnullable ?? true, - MapType = mapType - }; - if (colattr._IsNullable == null) colattr._IsNullable = tp?.isnullable; - if (string.IsNullOrEmpty(colattr.DbType)) colattr.DbType = tp?.dbtypeFull ?? "varchar(255)"; + var colattrIsNullable = colattr?._IsNullable; + var colattrIsNull = colattr == null; + if (colattr == null) + colattr = new ColumnAttribute + { + Name = csName, + DbType = tp.dbtypeFull, + IsNullable = tp.isnullable ?? true, + MapType = mapType + }; + if (colattr._IsNullable == null) colattr._IsNullable = tp?.isnullable; + if (string.IsNullOrEmpty(colattr.DbType)) colattr.DbType = tp?.dbtypeFull ?? "varchar(255)"; var isMySqlEnum = colattr.DbType.StartsWith("set(") || colattr.DbType.StartsWith("enum("); if (isMySqlEnum) - { - var leftBt = colattr.DbType.IndexOf('('); - colattr.DbType = colattr.DbType.Substring(0, leftBt).ToUpper() + colattr.DbType.Substring(leftBt); - } - else if (common._orm.Ado.DataType != DataType.ClickHouse) - colattr.DbType = colattr.DbType.ToUpper(); - - if (colattrIsNull == false && colattrIsNullable == true) colattr.DbType = colattr.DbType.Replace("NOT NULL", ""); - if (colattrIsNull == false && colattrIsNullable == false && colattr.DbType.Contains("NOT NULL") == false) colattr.DbType = Regex.Replace(colattr.DbType, @"\bNULL\b", "").Trim() + " NOT NULL"; - if (colattr._IsNullable == null && tp != null && tp.isnullable == null) colattr.IsNullable = tp.dbtypeFull.Contains("NOT NULL") == false; - if (colattr.DbType?.Contains("NOT NULL") == true) colattr.IsNullable = false; - if (string.IsNullOrEmpty(colattr.Name)) colattr.Name = csName; - if (common.CodeFirst.IsSyncStructureToLower) colattr.Name = colattr.Name.ToLower(); - if (common.CodeFirst.IsSyncStructureToUpper) colattr.Name = colattr.Name.ToUpper(); - - if ((colattr.IsNullable != true || colattr.IsIdentity == true || colattr.IsPrimary == true) && colattr.DbType.Contains("NOT NULL") == false && common._orm.Ado.DataType != DataType.ClickHouse) - { - colattr.IsNullable = false; - colattr.DbType = Regex.Replace(colattr.DbType, @"\bNULL\b", "").Trim() + " NOT NULL"; - } - if (colattr.IsNullable == true && colattr.DbType.Contains("NOT NULL")) colattr.DbType = colattr.DbType.Replace("NOT NULL", ""); - else if (colattr.IsNullable == true && !colattr.DbType.Contains("Nullable") && common._orm.Ado.DataType == DataType.ClickHouse) colattr.DbType = $"Nullable({colattr.DbType})"; + { + var leftBt = colattr.DbType.IndexOf('('); + colattr.DbType = colattr.DbType.Substring(0, leftBt).ToUpper() + colattr.DbType.Substring(leftBt); + } + else if (common._orm.Ado.DataType != DataType.ClickHouse) + colattr.DbType = colattr.DbType.ToUpper(); + + if (colattrIsNull == false && colattrIsNullable == true) colattr.DbType = colattr.DbType.Replace("NOT NULL", ""); + if (colattrIsNull == false && colattrIsNullable == false && colattr.DbType.Contains("NOT NULL") == false) colattr.DbType = Regex.Replace(colattr.DbType, @"\bNULL\b", "").Trim() + " NOT NULL"; + if (colattr._IsNullable == null && tp != null && tp.isnullable == null) colattr.IsNullable = tp.dbtypeFull.Contains("NOT NULL") == false; + if (colattr.DbType?.Contains("NOT NULL") == true) colattr.IsNullable = false; + if (string.IsNullOrEmpty(colattr.Name)) colattr.Name = csName; + if (common.CodeFirst.IsSyncStructureToLower) colattr.Name = colattr.Name.ToLower(); + if (common.CodeFirst.IsSyncStructureToUpper) colattr.Name = colattr.Name.ToUpper(); + + if ((colattr.IsNullable != true || colattr.IsIdentity == true || colattr.IsPrimary == true) && colattr.DbType.Contains("NOT NULL") == false && common._orm.Ado.DataType != DataType.ClickHouse) + { + colattr.IsNullable = false; + colattr.DbType = Regex.Replace(colattr.DbType, @"\bNULL\b", "").Trim() + " NOT NULL"; + } + if (colattr.IsNullable == true && colattr.DbType.Contains("NOT NULL")) colattr.DbType = colattr.DbType.Replace("NOT NULL", ""); + else if (colattr.IsNullable == true && !colattr.DbType.Contains("Nullable") && common._orm.Ado.DataType == DataType.ClickHouse) colattr.DbType = $"Nullable({colattr.DbType})"; if (isMySqlEnum == false) colattr.DbType = Regex.Replace(colattr.DbType, @"\([^\)]+\)", m => - { - var tmpLt = Regex.Replace(m.Groups[0].Value, @"\s", ""); - if (tmpLt.Contains("CHAR")) tmpLt = tmpLt.Replace("CHAR", " CHAR"); - if (tmpLt.Contains("BYTE")) tmpLt = tmpLt.Replace("BYTE", " BYTE"); - return tmpLt; - }); - if (colattr.IsIdentity == true && colattr.MapType.IsNumberType() == false) - colattr.IsIdentity = false; - if (isIgnore) colattr.IsIgnore = true; - - var col = new ColumnInfo - { - Table = trytb, - CsName = csName, - CsType = mapType, - Attribute = colattr - }; - - if (colattr.IsIgnore) - { - trytb.ColumnsByCsIgnore.Add(csName, col); + { + var tmpLt = Regex.Replace(m.Groups[0].Value, @"\s", ""); + if (tmpLt.Contains("CHAR")) tmpLt = tmpLt.Replace("CHAR", " CHAR"); + if (tmpLt.Contains("BYTE")) tmpLt = tmpLt.Replace("BYTE", " BYTE"); + return tmpLt; + }); + if (colattr.IsIdentity == true && colattr.MapType.IsNumberType() == false) + colattr.IsIdentity = false; + if (isIgnore) colattr.IsIgnore = true; + + var col = new ColumnInfo + { + Table = trytb, + CsName = csName, + CsType = mapType, + Attribute = colattr + }; + + if (colattr.IsIgnore) + { + trytb.ColumnsByCsIgnore.Add(csName, col); return null; - } - object defaultValue = null; - if (entityDefault != null) defaultValue = trytb.Properties[csName].GetValue(entityDefault, null); - if (defaultValue != null && mapType.IsEnum) - { + } + object defaultValue = null; + if (entityDefault != null) defaultValue = trytb.Properties[csName].GetValue(entityDefault, null); + if (defaultValue != null && mapType.IsEnum) + { Array enumValues = null; try { enumValues = Enum.GetValues(mapType); } //AOT error catch { } @@ -276,413 +274,413 @@ public static ColumnInfo ColumnAttributeToInfo(TableInfo trytb, object entityDef if (isEqualsEnumValue == false && enumValues.Length > 0) defaultValue = enumValues.GetValue(0); } - } - if (defaultValue != null && mapType != colattr.MapType) defaultValue = Utils.GetDataReaderValue(colattr.MapType, defaultValue); - if (defaultValue == null) defaultValue = tp?.defaultValue; - if (colattr.IsNullable == false && defaultValue == null) - { - var citype = colattr.MapType.IsNullableType() ? colattr.MapType.GetGenericArguments().FirstOrDefault() : colattr.MapType; - defaultValue = citype.CreateInstanceGetDefaultValue(); - } - try - { - var initParms = new List(); - col.DbDefaultValue = common.GetNoneParamaterSqlValue(initParms, "init", col, colattr.MapType, defaultValue); - if (initParms.Any()) col.DbDefaultValue = "NULL"; - } - catch - { - col.DbDefaultValue = "NULL"; - } - //if (defaultValue != null && colattr.MapType.NullableTypeOrThis() == typeof(DateTime)) - //{ - // var dt = (DateTime)defaultValue; - // if (Math.Abs(dt.Subtract(DateTime.Now).TotalSeconds) < 60) - // col.DbDefaultValue = common.Now; - // else if (Math.Abs(dt.Subtract(DateTime.UtcNow).TotalSeconds) < 60) - // col.DbDefaultValue = common.NowUtc; - //} - - if (common._orm.Ado.DataType == DataType.GBase) - { - if (colattr.IsIdentity == true) - { - var colType = col.CsType.NullableTypeOrThis(); - if (colType == typeof(int) || colType == typeof(uint)) - colattr.DbType = "SERIAL"; - else if (colType == typeof(long) || colType == typeof(ulong)) - colattr.DbType = "SERIAL8"; - } - if (colattr.MapType.NullableTypeOrThis() == typeof(DateTime)) - { - if (colattr._Precision == null) - { - colattr.DbType = "DATETIME YEAR TO FRACTION(3)"; - colattr.Precision = 3; - col.DbPrecision = 3; - } - else if (colattr._Precision == 0) - { - colattr.DbType = "DATETIME YEAR TO SECOND"; - } - else if (colattr._Precision > 0) - { - colattr.DbType = $"DATETIME YEAR TO FRACTION({colattr.Precision})"; - col.DbPrecision = (byte)colattr.Precision; - } - } - } - if (colattr.ServerTime != DateTimeKind.Unspecified && new[] { typeof(DateTime), typeof(DateTimeOffset) }.Contains(colattr.MapType.NullableTypeOrThis())) - { - var commonNow = common.Now; - var commonNowUtc = common.NowUtc; - switch (common._orm.Ado.DataType) - { - case DataType.MySql: - case DataType.OdbcMySql: //处理毫秒 - case DataType.CustomMySql: - var timeLength = 0; - var mTimeLength = Regex.Match(colattr.DbType, @"(DATETIME|TIMESTAMP)\s*\((\d+)\)"); - if (mTimeLength.Success) timeLength = int.Parse(mTimeLength.Groups[2].Value); - if (timeLength > 0 && timeLength < 7) - { - commonNow = $"{commonNow.TrimEnd('(', ')')}({timeLength})"; - commonNowUtc = $"{commonNowUtc.TrimEnd('(', ')')}({timeLength})"; - } - //https://github.com/dotnetcore/FreeSql/issues/1604 mysql 不支持默认值 utc_timestamp DDL - if (colattr.ServerTime == DateTimeKind.Local) - col.DbDefaultValue = commonNow; - break; - default: - col.DbDefaultValue = colattr.ServerTime == DateTimeKind.Local ? commonNow : commonNowUtc; - break; - } - col.DbInsertValue = colattr.ServerTime == DateTimeKind.Local ? commonNow : commonNowUtc; - col.DbUpdateValue = colattr.ServerTime == DateTimeKind.Local ? commonNow : commonNowUtc; - } - if (string.IsNullOrEmpty(colattr.InsertValueSql) == false) - { - col.DbDefaultValue = colattr.InsertValueSql; - col.DbInsertValue = colattr.InsertValueSql; - } - if (colattr.MapType.NullableTypeOrThis() == typeof(string) && colattr.StringLength != 0) - { - int strlen = colattr.StringLength; - var charPattern = @"(CHARACTER|CHAR2|CHAR)\s*(\([^\)]*\))?"; + } + if (defaultValue != null && mapType != colattr.MapType) defaultValue = Utils.GetDataReaderValue(colattr.MapType, defaultValue); + if (defaultValue == null) defaultValue = tp?.defaultValue; + if (colattr.IsNullable == false && defaultValue == null) + { + var citype = colattr.MapType.IsNullableType() ? colattr.MapType.GetGenericArguments().FirstOrDefault() : colattr.MapType; + defaultValue = citype.CreateInstanceGetDefaultValue(); + } + try + { + var initParms = new List(); + col.DbDefaultValue = common.GetNoneParamaterSqlValue(initParms, "init", col, colattr.MapType, defaultValue); + if (initParms.Any()) col.DbDefaultValue = "NULL"; + } + catch + { + col.DbDefaultValue = "NULL"; + } + //if (defaultValue != null && colattr.MapType.NullableTypeOrThis() == typeof(DateTime)) + //{ + // var dt = (DateTime)defaultValue; + // if (Math.Abs(dt.Subtract(DateTime.Now).TotalSeconds) < 60) + // col.DbDefaultValue = common.Now; + // else if (Math.Abs(dt.Subtract(DateTime.UtcNow).TotalSeconds) < 60) + // col.DbDefaultValue = common.NowUtc; + //} + + if (common._orm.Ado.DataType == DataType.GBase) + { + if (colattr.IsIdentity == true) + { + var colType = col.CsType.NullableTypeOrThis(); + if (colType == typeof(int) || colType == typeof(uint)) + colattr.DbType = "SERIAL"; + else if (colType == typeof(long) || colType == typeof(ulong)) + colattr.DbType = "SERIAL8"; + } + if (colattr.MapType.NullableTypeOrThis() == typeof(DateTime)) + { + if (colattr._Precision == null) + { + colattr.DbType = "DATETIME YEAR TO FRACTION(3)"; + colattr.Precision = 3; + col.DbPrecision = 3; + } + else if (colattr._Precision == 0) + { + colattr.DbType = "DATETIME YEAR TO SECOND"; + } + else if (colattr._Precision > 0) + { + colattr.DbType = $"DATETIME YEAR TO FRACTION({colattr.Precision})"; + col.DbPrecision = (byte)colattr.Precision; + } + } + } + if (colattr.ServerTime != DateTimeKind.Unspecified && new[] { typeof(DateTime), typeof(DateTimeOffset) }.Contains(colattr.MapType.NullableTypeOrThis())) + { + var commonNow = common.Now; + var commonNowUtc = common.NowUtc; + switch (common._orm.Ado.DataType) + { + case DataType.MySql: + case DataType.OdbcMySql: //处理毫秒 + case DataType.CustomMySql: + var timeLength = 0; + var mTimeLength = Regex.Match(colattr.DbType, @"(DATETIME|TIMESTAMP)\s*\((\d+)\)"); + if (mTimeLength.Success) timeLength = int.Parse(mTimeLength.Groups[2].Value); + if (timeLength > 0 && timeLength < 7) + { + commonNow = $"{commonNow.TrimEnd('(', ')')}({timeLength})"; + commonNowUtc = $"{commonNowUtc.TrimEnd('(', ')')}({timeLength})"; + } + //https://github.com/dotnetcore/FreeSql/issues/1604 mysql 不支持默认值 utc_timestamp DDL + if (colattr.ServerTime == DateTimeKind.Local) + col.DbDefaultValue = commonNow; + break; + default: + col.DbDefaultValue = colattr.ServerTime == DateTimeKind.Local ? commonNow : commonNowUtc; + break; + } + col.DbInsertValue = colattr.ServerTime == DateTimeKind.Local ? commonNow : commonNowUtc; + col.DbUpdateValue = colattr.ServerTime == DateTimeKind.Local ? commonNow : commonNowUtc; + } + if (string.IsNullOrEmpty(colattr.InsertValueSql) == false) + { + col.DbDefaultValue = colattr.InsertValueSql; + col.DbInsertValue = colattr.InsertValueSql; + } + if (colattr.MapType.NullableTypeOrThis() == typeof(string) && colattr.StringLength != 0) + { + int strlen = colattr.StringLength; + var charPattern = @"(CHARACTER|CHAR2|CHAR)\s*(\([^\)]*\))?"; var replaceCounter = 0; - var strNotNull = colattr.IsNullable == false ? " NOT NULL" : ""; - switch (common._orm.Ado.DataType) - { - case DataType.MySql: - case DataType.OdbcMySql: - case DataType.CustomMySql: + var strNotNull = colattr.IsNullable == false ? " NOT NULL" : ""; + switch (common._orm.Ado.DataType) + { + case DataType.MySql: + case DataType.OdbcMySql: + case DataType.CustomMySql: if (strlen == -2) colattr.DbType = $"LONGTEXT{strNotNull}"; else if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}"; else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - case DataType.SqlServer: - case DataType.OdbcSqlServer: - case DataType.CustomSqlServer: - if (strlen < 0) colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}(MAX)" : m.Groups[0].Value); - else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - case DataType.PostgreSQL: - case DataType.OdbcPostgreSQL: - case DataType.CustomPostgreSQL: - case DataType.KingbaseES: - case DataType.OdbcKingbaseES: - case DataType.ShenTong: - if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}"; - else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - case DataType.Oracle: - case DataType.CustomOracle: - if (strlen < 0) colattr.DbType = $"NCLOB{strNotNull}"; //v1.3.2+ https://github.com/dotnetcore/FreeSql/issues/259 - else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - case DataType.Dameng: - if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}"; - else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - case DataType.OdbcOracle: - case DataType.OdbcDameng: - if (strlen < 0) colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}(4000)" : m.Groups[0].Value); //ODBC 不支持 NCLOB - else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - case DataType.Sqlite: - if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}"; - else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - case DataType.MsAccess: - charPattern = @"(CHAR|CHAR2|CHARACTER|TEXT)\s*(\([^\)]*\))?"; - if (strlen < 0) colattr.DbType = $"LONGTEXT{strNotNull}"; - else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - case DataType.Firebird: - charPattern = @"(CHAR|CHAR2|CHARACTER|TEXT)\s*(\([^\)]*\))?"; - if (strlen < 0) colattr.DbType = $"BLOB SUB_TYPE 1{strNotNull}"; - else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - case DataType.GBase: - if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}"; - else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => - replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); - break; - } - } - if (colattr.MapType == typeof(string) && colattr.IsVersion == true) colattr.StringLength = 40; - if (colattr.MapType == typeof(byte[]) && colattr.IsVersion == true) colattr.StringLength = 16; // 8=sqlserver timestamp, 16=GuidToBytes - if (colattr.MapType == typeof(byte[]) && colattr.StringLength != 0) - { - int strlen = colattr.StringLength; - var bytePattern = @"(VARBINARY|BINARY|BYTEA)\s*(\([^\)]*\))?"; - var strNotNull = colattr.IsNullable == false ? " NOT NULL" : ""; - switch (common._orm.Ado.DataType) - { - case DataType.MySql: - case DataType.OdbcMySql: - case DataType.CustomMySql: - if (strlen == -2) colattr.DbType = $"LONGBLOB{strNotNull}"; - else if (strlen < 0) colattr.DbType = $"BLOB{strNotNull}"; - else colattr.DbType = Regex.Replace(colattr.DbType, bytePattern, $"$1({strlen})"); - break; - case DataType.SqlServer: - case DataType.OdbcSqlServer: - case DataType.CustomSqlServer: - if (strlen < 0) colattr.DbType = Regex.Replace(colattr.DbType, bytePattern, $"$1(MAX)"); - else colattr.DbType = Regex.Replace(colattr.DbType, bytePattern, $"$1({strlen})"); - break; - case DataType.PostgreSQL: - case DataType.OdbcPostgreSQL: - case DataType.CustomPostgreSQL: - case DataType.KingbaseES: - case DataType.OdbcKingbaseES: - case DataType.ShenTong: //驱动引发的异常:“System.Data.OscarClient.OscarException”(位于 System.Data.OscarClient.dll 中) - colattr.DbType = $"BYTEA{strNotNull}"; //变长二进制串 - break; - case DataType.Oracle: - case DataType.CustomOracle: - colattr.DbType = $"BLOB{strNotNull}"; - break; - case DataType.Dameng: - colattr.DbType = $"BLOB{strNotNull}"; - break; - case DataType.OdbcOracle: - case DataType.OdbcDameng: - colattr.DbType = $"BLOB{strNotNull}"; - break; - case DataType.Sqlite: - colattr.DbType = $"BLOB{strNotNull}"; - break; - case DataType.MsAccess: - if (strlen < 0) colattr.DbType = $"BLOB{strNotNull}"; - else colattr.DbType = Regex.Replace(colattr.DbType, bytePattern, $"$1({strlen})"); - break; - case DataType.Firebird: - colattr.DbType = $"BLOB{strNotNull}"; - break; - case DataType.GBase: - colattr.DbType = $"BYTE{strNotNull}"; - break; - } - } - if (colattr.MapType.NullableTypeOrThis() == typeof(decimal) && (colattr.Precision > 0 || colattr.Scale > 0)) - { - if (colattr.Precision <= 0) colattr.Precision = 10; - if (colattr.Scale <= 0) colattr.Scale = 0; - var decimalPatten = @"(DECIMAL|NUMERIC|NUMBER)\s*(\([^\)]*\))?"; - colattr.DbType = Regex.Replace(colattr.DbType, decimalPatten, $"$1({colattr.Precision},{colattr.Scale})"); - } - - if (trytb.Columns.ContainsKey(colattr.Name)) throw new Exception(CoreStrings.Duplicate_ColumnAttribute(colattr.Name)); - if (trytb.ColumnsByCs.ContainsKey(csName)) throw new Exception(CoreStrings.Duplicate_PropertyName(csName)); + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + case DataType.SqlServer: + case DataType.OdbcSqlServer: + case DataType.CustomSqlServer: + if (strlen < 0) colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}(MAX)" : m.Groups[0].Value); + else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + case DataType.PostgreSQL: + case DataType.OdbcPostgreSQL: + case DataType.CustomPostgreSQL: + case DataType.KingbaseES: + case DataType.OdbcKingbaseES: + case DataType.ShenTong: + if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}"; + else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + case DataType.Oracle: + case DataType.CustomOracle: + if (strlen < 0) colattr.DbType = $"NCLOB{strNotNull}"; //v1.3.2+ https://github.com/dotnetcore/FreeSql/issues/259 + else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + case DataType.Dameng: + if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}"; + else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + case DataType.OdbcOracle: + case DataType.OdbcDameng: + if (strlen < 0) colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}(4000)" : m.Groups[0].Value); //ODBC 不支持 NCLOB + else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + case DataType.Sqlite: + if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}"; + else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + case DataType.MsAccess: + charPattern = @"(CHAR|CHAR2|CHARACTER|TEXT)\s*(\([^\)]*\))?"; + if (strlen < 0) colattr.DbType = $"LONGTEXT{strNotNull}"; + else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + case DataType.Firebird: + charPattern = @"(CHAR|CHAR2|CHARACTER|TEXT)\s*(\([^\)]*\))?"; + if (strlen < 0) colattr.DbType = $"BLOB SUB_TYPE 1{strNotNull}"; + else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + case DataType.GBase: + if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}"; + else colattr.DbType = Regex.Replace(colattr.DbType, charPattern, m => + replaceCounter++ == 0 ? $"{m.Groups[1].Value}({strlen})" : m.Groups[0].Value); + break; + } + } + if (colattr.MapType == typeof(string) && colattr.IsVersion == true) colattr.StringLength = 40; + if (colattr.MapType == typeof(byte[]) && colattr.IsVersion == true) colattr.StringLength = 16; // 8=sqlserver timestamp, 16=GuidToBytes + if (colattr.MapType == typeof(byte[]) && colattr.StringLength != 0) + { + int strlen = colattr.StringLength; + var bytePattern = @"(VARBINARY|BINARY|BYTEA)\s*(\([^\)]*\))?"; + var strNotNull = colattr.IsNullable == false ? " NOT NULL" : ""; + switch (common._orm.Ado.DataType) + { + case DataType.MySql: + case DataType.OdbcMySql: + case DataType.CustomMySql: + if (strlen == -2) colattr.DbType = $"LONGBLOB{strNotNull}"; + else if (strlen < 0) colattr.DbType = $"BLOB{strNotNull}"; + else colattr.DbType = Regex.Replace(colattr.DbType, bytePattern, $"$1({strlen})"); + break; + case DataType.SqlServer: + case DataType.OdbcSqlServer: + case DataType.CustomSqlServer: + if (strlen < 0) colattr.DbType = Regex.Replace(colattr.DbType, bytePattern, $"$1(MAX)"); + else colattr.DbType = Regex.Replace(colattr.DbType, bytePattern, $"$1({strlen})"); + break; + case DataType.PostgreSQL: + case DataType.OdbcPostgreSQL: + case DataType.CustomPostgreSQL: + case DataType.KingbaseES: + case DataType.OdbcKingbaseES: + case DataType.ShenTong: //驱动引发的异常:“System.Data.OscarClient.OscarException”(位于 System.Data.OscarClient.dll 中) + colattr.DbType = $"BYTEA{strNotNull}"; //变长二进制串 + break; + case DataType.Oracle: + case DataType.CustomOracle: + colattr.DbType = $"BLOB{strNotNull}"; + break; + case DataType.Dameng: + colattr.DbType = $"BLOB{strNotNull}"; + break; + case DataType.OdbcOracle: + case DataType.OdbcDameng: + colattr.DbType = $"BLOB{strNotNull}"; + break; + case DataType.Sqlite: + colattr.DbType = $"BLOB{strNotNull}"; + break; + case DataType.MsAccess: + if (strlen < 0) colattr.DbType = $"BLOB{strNotNull}"; + else colattr.DbType = Regex.Replace(colattr.DbType, bytePattern, $"$1({strlen})"); + break; + case DataType.Firebird: + colattr.DbType = $"BLOB{strNotNull}"; + break; + case DataType.GBase: + colattr.DbType = $"BYTE{strNotNull}"; + break; + } + } + if (colattr.MapType.NullableTypeOrThis() == typeof(decimal) && (colattr.Precision > 0 || colattr.Scale > 0)) + { + if (colattr.Precision <= 0) colattr.Precision = 10; + if (colattr.Scale <= 0) colattr.Scale = 0; + var decimalPatten = @"(DECIMAL|NUMERIC|NUMBER)\s*(\([^\)]*\))?"; + colattr.DbType = Regex.Replace(colattr.DbType, decimalPatten, $"$1({colattr.Precision},{colattr.Scale})"); + } + + if (trytb.Columns.ContainsKey(colattr.Name)) throw new Exception(CoreStrings.Duplicate_ColumnAttribute(colattr.Name)); + if (trytb.ColumnsByCs.ContainsKey(csName)) throw new Exception(CoreStrings.Duplicate_PropertyName(csName)); return col; - } + } public static void AuditTableInfo(TableInfo trytb, TableAttribute tbattr, IEnumerable indexes, List columnsList, CommonUtils common) { - trytb.VersionColumn = trytb.Columns.Values.Where(a => a.Attribute.IsVersion == true).LastOrDefault(); - if (trytb.VersionColumn != null) - { - if (trytb.VersionColumn.Attribute.MapType.IsNullableType() || - trytb.VersionColumn.Attribute.MapType.IsNumberType() == false && !new[] { typeof(byte[]), typeof(string) }.Contains(trytb.VersionColumn.Attribute.MapType)) - throw new Exception(CoreStrings.Properties_AsRowLock_Must_Numeric_Byte(trytb.VersionColumn.CsName)); - } - tbattr?.ParseAsTable(trytb); - - var indexesDict = new Dictionary(StringComparer.CurrentCultureIgnoreCase); - //从数据库查找主键、自增、索引 - if (common.CodeFirst.IsConfigEntityFromDbFirst) - { - try - { - if (common._orm.DbFirst != null) - { - if (common.dbTables == null) - lock (common.dbTablesLock) - if (common.dbTables == null) - common.dbTables = common._orm.DbFirst.GetTablesByDatabase(); - - var finddbtbs = common.dbTables.Where(a => string.Compare(a.Name, trytb.CsName, true) == 0 || string.Compare(a.Name, trytb.DbName, true) == 0); - foreach (var dbtb in finddbtbs) - { - foreach (var dbident in dbtb.Identitys) - { - if (trytb.Columns.TryGetValue(dbident.Name, out var trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbident.CsType.NullableTypeOrThis() || - trytb.ColumnsByCs.TryGetValue(dbident.Name, out trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbident.CsType.NullableTypeOrThis()) - trycol.Attribute.IsIdentity = true; - } - foreach (var dbpk in dbtb.Primarys) - { - if (trytb.Columns.TryGetValue(dbpk.Name, out var trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbpk.CsType.NullableTypeOrThis() || - trytb.ColumnsByCs.TryGetValue(dbpk.Name, out trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbpk.CsType.NullableTypeOrThis()) - trycol.Attribute.IsPrimary = true; - } - foreach (var dbidx in dbtb.IndexesDict) - { - var indexColumns = new List(); - foreach (var dbcol in dbidx.Value.Columns) - { - if (trytb.Columns.TryGetValue(dbcol.Column.Name, out var trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbcol.Column.CsType.NullableTypeOrThis() || - trytb.ColumnsByCs.TryGetValue(dbcol.Column.Name, out trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbcol.Column.CsType.NullableTypeOrThis()) - indexColumns.Add(new IndexColumnInfo - { - Column = trycol, - IsDesc = dbcol.IsDesc - }); - } - if (indexColumns.Any() == false) continue; - if (indexesDict.ContainsKey(dbidx.Key)) indexesDict.Remove(dbidx.Key); - indexesDict.Add(dbidx.Key, new IndexInfo - { - Name = dbidx.Key, - Columns = indexColumns.ToArray(), - IsUnique = dbidx.Value.IsUnique, - IndexMethod = IndexMethod.B_Tree - }); - } - } - } - } - catch { } - } - //索引和唯一键 - foreach (var index in indexes) - { - var val = index.Fields?.Trim(' ', '\t', ','); - if (string.IsNullOrEmpty(val)) continue; - var arr = val.Split(',').Select(a => a.Trim(' ', '\t').Trim()).Where(a => !string.IsNullOrEmpty(a)).ToArray(); - if (arr.Any() == false) continue; - var indexColumns = new List(); - foreach (var field in arr) - { - var idxcol = new IndexColumnInfo(); - if (field.EndsWith(" DESC", StringComparison.CurrentCultureIgnoreCase)) idxcol.IsDesc = true; - var colname = Regex.Replace(field, " (DESC|ASC)", "", RegexOptions.IgnoreCase); - if (trytb.ColumnsByCs.TryGetValue(colname, out var trycol) || trytb.Columns.TryGetValue(colname, out trycol)) - { - idxcol.Column = trycol; - indexColumns.Add(idxcol); - } - } - if (indexColumns.Any() == false) continue; - var indexName = common.CodeFirst.IsSyncStructureToLower ? index.Name.ToLower() : (common.CodeFirst.IsSyncStructureToUpper ? index.Name.ToUpper() : index.Name); - if (indexesDict.ContainsKey(indexName)) indexesDict.Remove(indexName); - indexesDict.Add(indexName, new IndexInfo - { - Name = indexName, - Columns = indexColumns.ToArray(), - IsUnique = index.IsUnique, - IndexMethod = index.IndexMethod - }); - } - trytb.Indexes = indexesDict.Values.ToArray(); - - trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray(); - if (trytb.Primarys.Any() == false) - { - trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute._IsPrimary == null && string.Compare(a.Attribute.Name, "id", true) == 0).ToArray(); - if (trytb.Primarys.Any() == false) - { - var identcol = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity == true).FirstOrDefault(); - if (identcol != null) trytb.Primarys = new[] { identcol }; - if (trytb.Primarys.Any() == false) - { - trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute._IsPrimary == null && string.Compare(a.Attribute.Name, $"{trytb.DbName}id", true) == 0).ToArray(); - if (trytb.Primarys.Any() == false) - { - trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute._IsPrimary == null && string.Compare(a.Attribute.Name, $"{trytb.DbName}_id", true) == 0).ToArray(); - } - } - } - foreach (var col in trytb.Primarys) - col.Attribute.IsPrimary = true; - } - foreach (var col in trytb.Primarys) - { - col.Attribute.IsNullable = false; - col.Attribute.DbType = col.Attribute.DbType.Replace("NOT NULL", "").Replace(" NULL", "").Trim(); - switch (common._orm.Ado.DataType) - { - case DataType.Sqlite: - col.Attribute.DbType += " NOT NULL"; //sqlite 主键也可以插入 null - break; - } - } - foreach (var col in trytb.Columns.Values) - { - if (col.Attribute.IsPrimary == false && col.Attribute.IsIdentity) col.Attribute.CanUpdate = false; - var ltp = @"\(([^\)]+)\)"; - col.DbTypeText = Regex.Replace(col.Attribute.DbType.Replace("NOT NULL", "").Replace(" NULL", "").Trim(), ltp, ""); - var m = Regex.Match(col.Attribute.DbType, ltp); - if (m.Success == false) continue; - var sizeStr = m.Groups[1].Value.Trim(); - if (sizeStr.EndsWith(" BYTE") || sizeStr.EndsWith(" CHAR")) sizeStr = sizeStr.Remove(sizeStr.Length - 5); //ORACLE - if (string.Compare(sizeStr, "max", true) == 0) - { - col.DbSize = -1; - continue; - } - var sizeArr = sizeStr.Split(','); - if (int.TryParse(sizeArr[0].Trim(), out var size) == false) continue; - if (col.Attribute.MapType.NullableTypeOrThis() == typeof(DateTime)) - { - col.DbScale = (byte)size; - if (col.Attribute.Scale <= 0) col.Attribute.Scale = col.DbScale; - continue; - } - if (sizeArr.Length == 1) - { - col.DbSize = size; - if (col.Attribute.StringLength <= 0) col.Attribute.StringLength = col.DbSize; - continue; - } - if (byte.TryParse(sizeArr[1], out var scale) == false) continue; - col.DbPrecision = (byte)size; - col.DbScale = scale; - if (col.Attribute.Precision <= 0) - { - col.Attribute.Precision = col.DbPrecision; - col.Attribute.Scale = col.DbScale; - } - } - trytb.IsRereadSql = trytb.Columns.Where(a => string.IsNullOrWhiteSpace(a.Value.Attribute.RereadSql) == false).Any(); - trytb.ColumnsByPosition = columnsList.Where(a => a.Attribute.Position > 0).OrderBy(a => a.Attribute.Position) - .Concat(columnsList.Where(a => a.Attribute.Position == 0)) - .Concat(columnsList.Where(a => a.Attribute.Position < 0).OrderBy(a => a.Attribute.Position)).ToArray(); - trytb.ColumnsByCanUpdateDbUpdateValue = columnsList.Where(a => a.Attribute.CanUpdate == true && string.IsNullOrEmpty(a.DbUpdateValue) == false).ToArray(); - } + trytb.VersionColumn = trytb.Columns.Values.Where(a => a.Attribute.IsVersion == true).LastOrDefault(); + if (trytb.VersionColumn != null) + { + if (trytb.VersionColumn.Attribute.MapType.IsNullableType() || + trytb.VersionColumn.Attribute.MapType.IsNumberType() == false && !new[] { typeof(byte[]), typeof(string) }.Contains(trytb.VersionColumn.Attribute.MapType)) + throw new Exception(CoreStrings.Properties_AsRowLock_Must_Numeric_Byte(trytb.VersionColumn.CsName)); + } + tbattr?.ParseAsTable(trytb); + + var indexesDict = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + //从数据库查找主键、自增、索引 + if (common.CodeFirst.IsConfigEntityFromDbFirst) + { + try + { + if (common._orm.DbFirst != null) + { + if (common.dbTables == null) + lock (common.dbTablesLock) + if (common.dbTables == null) + common.dbTables = common._orm.DbFirst.GetTablesByDatabase(); + + var finddbtbs = common.dbTables.Where(a => string.Compare(a.Name, trytb.CsName, true) == 0 || string.Compare(a.Name, trytb.DbName, true) == 0); + foreach (var dbtb in finddbtbs) + { + foreach (var dbident in dbtb.Identitys) + { + if (trytb.Columns.TryGetValue(dbident.Name, out var trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbident.CsType.NullableTypeOrThis() || + trytb.ColumnsByCs.TryGetValue(dbident.Name, out trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbident.CsType.NullableTypeOrThis()) + trycol.Attribute.IsIdentity = true; + } + foreach (var dbpk in dbtb.Primarys) + { + if (trytb.Columns.TryGetValue(dbpk.Name, out var trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbpk.CsType.NullableTypeOrThis() || + trytb.ColumnsByCs.TryGetValue(dbpk.Name, out trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbpk.CsType.NullableTypeOrThis()) + trycol.Attribute.IsPrimary = true; + } + foreach (var dbidx in dbtb.IndexesDict) + { + var indexColumns = new List(); + foreach (var dbcol in dbidx.Value.Columns) + { + if (trytb.Columns.TryGetValue(dbcol.Column.Name, out var trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbcol.Column.CsType.NullableTypeOrThis() || + trytb.ColumnsByCs.TryGetValue(dbcol.Column.Name, out trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbcol.Column.CsType.NullableTypeOrThis()) + indexColumns.Add(new IndexColumnInfo + { + Column = trycol, + IsDesc = dbcol.IsDesc + }); + } + if (indexColumns.Any() == false) continue; + if (indexesDict.ContainsKey(dbidx.Key)) indexesDict.Remove(dbidx.Key); + indexesDict.Add(dbidx.Key, new IndexInfo + { + Name = dbidx.Key, + Columns = indexColumns.ToArray(), + IsUnique = dbidx.Value.IsUnique, + IndexMethod = IndexMethod.B_Tree + }); + } + } + } + } + catch { } + } + //索引和唯一键 + foreach (var index in indexes) + { + var val = index.Fields?.Trim(' ', '\t', ','); + if (string.IsNullOrEmpty(val)) continue; + var arr = val.Split(',').Select(a => a.Trim(' ', '\t').Trim()).Where(a => !string.IsNullOrEmpty(a)).ToArray(); + if (arr.Any() == false) continue; + var indexColumns = new List(); + foreach (var field in arr) + { + var idxcol = new IndexColumnInfo(); + if (field.EndsWith(" DESC", StringComparison.CurrentCultureIgnoreCase)) idxcol.IsDesc = true; + var colname = Regex.Replace(field, " (DESC|ASC)", "", RegexOptions.IgnoreCase); + if (trytb.ColumnsByCs.TryGetValue(colname, out var trycol) || trytb.Columns.TryGetValue(colname, out trycol)) + { + idxcol.Column = trycol; + indexColumns.Add(idxcol); + } + } + if (indexColumns.Any() == false) continue; + var indexName = common.CodeFirst.IsSyncStructureToLower ? index.Name.ToLower() : (common.CodeFirst.IsSyncStructureToUpper ? index.Name.ToUpper() : index.Name); + if (indexesDict.ContainsKey(indexName)) indexesDict.Remove(indexName); + indexesDict.Add(indexName, new IndexInfo + { + Name = indexName, + Columns = indexColumns.ToArray(), + IsUnique = index.IsUnique, + IndexMethod = index.IndexMethod + }); + } + trytb.Indexes = indexesDict.Values.ToArray(); + + trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray(); + if (trytb.Primarys.Any() == false) + { + trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute._IsPrimary == null && string.Compare(a.Attribute.Name, "id", true) == 0).ToArray(); + if (trytb.Primarys.Any() == false) + { + var identcol = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity == true).FirstOrDefault(); + if (identcol != null) trytb.Primarys = new[] { identcol }; + if (trytb.Primarys.Any() == false) + { + trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute._IsPrimary == null && string.Compare(a.Attribute.Name, $"{trytb.DbName}id", true) == 0).ToArray(); + if (trytb.Primarys.Any() == false) + { + trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute._IsPrimary == null && string.Compare(a.Attribute.Name, $"{trytb.DbName}_id", true) == 0).ToArray(); + } + } + } + foreach (var col in trytb.Primarys) + col.Attribute.IsPrimary = true; + } + foreach (var col in trytb.Primarys) + { + col.Attribute.IsNullable = false; + col.Attribute.DbType = col.Attribute.DbType.Replace("NOT NULL", "").Replace(" NULL", "").Trim(); + switch (common._orm.Ado.DataType) + { + case DataType.Sqlite: + col.Attribute.DbType += " NOT NULL"; //sqlite 主键也可以插入 null + break; + } + } + foreach (var col in trytb.Columns.Values) + { + if (col.Attribute.IsPrimary == false && col.Attribute.IsIdentity) col.Attribute.CanUpdate = false; + var ltp = @"\(([^\)]+)\)"; + col.DbTypeText = Regex.Replace(col.Attribute.DbType.Replace("NOT NULL", "").Replace(" NULL", "").Trim(), ltp, ""); + var m = Regex.Match(col.Attribute.DbType, ltp); + if (m.Success == false) continue; + var sizeStr = m.Groups[1].Value.Trim(); + if (sizeStr.EndsWith(" BYTE") || sizeStr.EndsWith(" CHAR")) sizeStr = sizeStr.Remove(sizeStr.Length - 5); //ORACLE + if (string.Compare(sizeStr, "max", true) == 0) + { + col.DbSize = -1; + continue; + } + var sizeArr = sizeStr.Split(','); + if (int.TryParse(sizeArr[0].Trim(), out var size) == false) continue; + if (col.Attribute.MapType.NullableTypeOrThis() == typeof(DateTime)) + { + col.DbScale = (byte)size; + if (col.Attribute.Scale <= 0) col.Attribute.Scale = col.DbScale; + continue; + } + if (sizeArr.Length == 1) + { + col.DbSize = size; + if (col.Attribute.StringLength <= 0) col.Attribute.StringLength = col.DbSize; + continue; + } + if (byte.TryParse(sizeArr[1], out var scale) == false) continue; + col.DbPrecision = (byte)size; + col.DbScale = scale; + if (col.Attribute.Precision <= 0) + { + col.Attribute.Precision = col.DbPrecision; + col.Attribute.Scale = col.DbScale; + } + } + trytb.IsRereadSql = trytb.Columns.Where(a => string.IsNullOrWhiteSpace(a.Value.Attribute.RereadSql) == false).Any(); + trytb.ColumnsByPosition = columnsList.Where(a => a.Attribute.Position > 0).OrderBy(a => a.Attribute.Position) + .Concat(columnsList.Where(a => a.Attribute.Position == 0)) + .Concat(columnsList.Where(a => a.Attribute.Position < 0).OrderBy(a => a.Attribute.Position)).ToArray(); + trytb.ColumnsByCanUpdateDbUpdateValue = columnsList.Where(a => a.Attribute.CanUpdate == true && string.IsNullOrEmpty(a.DbUpdateValue) == false).ToArray(); + } public static void AddTableRef(CommonUtils common, TableInfo trytb, PropertyInfo pnv, bool isLazy, NativeTuple vp, StringBuilder cscode) { var getMethod = vp?.Item4; @@ -1687,7 +1685,8 @@ public static T[] GetDbParamtersByObject(string sql, object obj, string param //[typeof(JObject)] = true, //[typeof(JArray)] = true, }; - internal static ConcurrentDictionary>> _dicExecuteArrayRowReadClassOrTuple = new ConcurrentDictionary>>(); + internal static ConcurrentDictionary>> _dicExecuteArrayRowReadClassOrTuple + = Utils.GlobalCacheFactory.CreateCacheItem>>>(); internal class RowInfo { public object Value { get; set; } @@ -2111,7 +2110,7 @@ internal static RowInfo ExecuteArrayRowReadAnonymousType(Type type2, int[] index internal static MethodInfo MethodExecuteArrayRowReadClassOrTuple = typeof(Utils).GetMethod("ExecuteArrayRowReadClassOrTuple", BindingFlags.Static | BindingFlags.NonPublic); internal static MethodInfo MethodGetDataReaderValue = typeof(Utils).GetMethod("GetDataReaderValue", BindingFlags.Static | BindingFlags.NonPublic); - static ConcurrentDictionary> _dicFillPropertyValue = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicFillPropertyValue = Utils.GlobalCacheFactory.CreateCacheItem>>(); internal static void FillPropertyValue(object info, string memberAccessPath, object value) { var typeObj = info.GetType(); @@ -2163,13 +2162,13 @@ public static char StringToChar(string str) return str.ToCharArray(0, 1)[0]; } - static ConcurrentDictionary>> _dicGetDataReaderValue = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicGetDataReaderValue = Utils.GlobalCacheFactory.CreateCacheItem>>>(); static MethodInfo MethodArrayGetValue = typeof(Array).GetMethod("GetValue", new[] { typeof(int) }); static MethodInfo MethodArrayGetLength = typeof(Array).GetMethod("GetLength", new[] { typeof(int) }); static MethodInfo MethodGuidTryParse = typeof(Guid).GetMethod("TryParse", new[] { typeof(string), typeof(Guid).MakeByRefType() }); static MethodInfo MethodEnumParse = typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(string), typeof(bool) }); static MethodInfo MethodConvertChangeType = typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) }); - static MethodInfo MethodTimeSpanFromSeconds = typeof(TimeSpan).GetMethod("FromSeconds", new[] { typeof(double) } ); + static MethodInfo MethodTimeSpanFromSeconds = typeof(TimeSpan).GetMethod("FromSeconds", new[] { typeof(double) }); static MethodInfo MethodSByteTryParse = typeof(sbyte).GetMethod("TryParse", new[] { typeof(string), typeof(sbyte).MakeByRefType() }); static MethodInfo MethodShortTryParse = typeof(short).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(short).MakeByRefType() }); static MethodInfo MethodIntTryParse = typeof(int).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(int).MakeByRefType() }); @@ -2198,10 +2197,10 @@ public static char StringToChar(string str) static MethodInfo MethodBytesToGuid = typeof(Utils).GetMethod("BytesToGuid", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(byte[]) }, null); - public static ConcurrentDictionary TypeHandlers { get; } = new ConcurrentDictionary(); - public static ConcurrentBag> GetDataReaderValueBlockExpressionSwitchTypeFullName = new ConcurrentBag>(); - public static ConcurrentBag> GetDataReaderValueBlockExpressionObjectToStringIfThenElse = new ConcurrentBag>(); - public static ConcurrentBag> GetDataReaderValueBlockExpressionObjectToBytesIfThenElse = new ConcurrentBag>(); + public static ConcurrentDictionary TypeHandlers { get; } = Utils.GlobalCacheFactory.CreateCacheItem>(); + public static ConcurrentBag> GetDataReaderValueBlockExpressionSwitchTypeFullName = Utils.GlobalCacheFactory.CreateCacheItem>>(); + public static ConcurrentBag> GetDataReaderValueBlockExpressionObjectToStringIfThenElse = Utils.GlobalCacheFactory.CreateCacheItem>>(); + public static ConcurrentBag> GetDataReaderValueBlockExpressionObjectToBytesIfThenElse = Utils.GlobalCacheFactory.CreateCacheItem>>(); public static Expression GetDataReaderValueBlockExpression(Type type, Expression value) { var returnTarget = Expression.Label(typeof(object)); diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseAdo/ClickHouseConnectionPool.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseAdo/ClickHouseConnectionPool.cs index 62f8983b5..33bce3325 100644 --- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseAdo/ClickHouseConnectionPool.cs +++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseAdo/ClickHouseConnectionPool.cs @@ -67,7 +67,7 @@ class ClickHouseConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Custom/CustomProvider.cs b/Providers/FreeSql.Provider.Custom/CustomProvider.cs index ce223f39a..3527d82ce 100644 --- a/Providers/FreeSql.Provider.Custom/CustomProvider.cs +++ b/Providers/FreeSql.Provider.Custom/CustomProvider.cs @@ -86,11 +86,11 @@ public override void Dispose() public static class FreeSqlCustomAdapterGlobalExtensions { internal static CustomAdapter DefaultAdapter = new CustomAdapter(); - internal static ConcurrentDictionary _dicCustomAdater = new ConcurrentDictionary(); + internal static ConcurrentDictionary _dicCustomAdater = Utils.GlobalCacheFactory.CreateCacheItem>(); public static void SetCustomAdapter(this IFreeSql that, CustomAdapter adapter) => _dicCustomAdater.AddOrUpdate(that.Ado.Identifier, adapter, (fsql, old) => adapter); internal static CustomAdapter GetCustomAdapter(this IFreeSql that) => _dicCustomAdater.TryGetValue(that.Ado.Identifier, out var tryada) ? tryada : DefaultAdapter; - internal static ConcurrentDictionary _dicDbProviderFactory = new ConcurrentDictionary(); + internal static ConcurrentDictionary _dicDbProviderFactory = Utils.GlobalCacheFactory.CreateCacheItem>(); public static void SetDbProviderFactory(this IFreeSql that, DbProviderFactory factory) => _dicDbProviderFactory.AddOrUpdate(that.Ado.Identifier, factory, (fsql, old) => factory); internal static DbProviderFactory GetDbProviderFactory(this IFreeSql that) => _dicDbProviderFactory.TryGetValue(that.Ado.Identifier, out var trydbpf) ? trydbpf : throw new Exception("需要先设置 fsql.SetDbProviderFactory(..) 方法"); } diff --git a/Providers/FreeSql.Provider.Custom/Oracle/CustomOracleDbFirst.cs b/Providers/FreeSql.Provider.Custom/Oracle/CustomOracleDbFirst.cs index e3a9efc66..552381b2e 100644 --- a/Providers/FreeSql.Provider.Custom/Oracle/CustomOracleDbFirst.cs +++ b/Providers/FreeSql.Provider.Custom/Oracle/CustomOracleDbFirst.cs @@ -115,7 +115,7 @@ DbType GetSqlDbType(DbColumnInfo column) throw new NotImplementedException(CoreStrings.S_TypeMappingNotImplemented(column.DbTypeTextFull)); } - static ConcurrentDictionary _dicDbToCs = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary _dicDbToCs = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); static CustomOracleDbFirst() { var defaultDbToCs = new Dictionary() { diff --git a/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengConnectionPool.cs b/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengConnectionPool.cs index 11a515317..0daad0275 100644 --- a/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengConnectionPool.cs +++ b/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengConnectionPool.cs @@ -64,7 +64,7 @@ class DamengConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Dameng/DamengDbFirst.cs b/Providers/FreeSql.Provider.Dameng/DamengDbFirst.cs index d48d4219e..2ad8bb482 100644 --- a/Providers/FreeSql.Provider.Dameng/DamengDbFirst.cs +++ b/Providers/FreeSql.Provider.Dameng/DamengDbFirst.cs @@ -57,10 +57,10 @@ DmDbType GetSqlDbType(DbColumnInfo column) } if (dbfull?.StartsWith("datetime(") == true) { - _dicDbToCs.TryAdd(dbfull, _dicDbToCs["timestamp(6)"]); - return DmDbType.DateTime; + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["timestamp(6)"]); + return DmDbType.DateTime; } - switch (column.DbTypeText?.ToLower()) + switch (column.DbTypeText?.ToLower()) { case "bit": _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(1)"]); @@ -168,7 +168,7 @@ DmDbType GetSqlDbType(DbColumnInfo column) throw new NotImplementedException(CoreStrings.S_TypeMappingNotImplemented(column.DbTypeTextFull)); } - static ConcurrentDictionary _dicDbToCs = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary _dicDbToCs = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); static DamengDbFirst() { var defaultDbToCs = new Dictionary() { diff --git a/Providers/FreeSql.Provider.Firebird/FirebirdAdo/FirebirdConnectionPool.cs b/Providers/FreeSql.Provider.Firebird/FirebirdAdo/FirebirdConnectionPool.cs index 407b61750..0ccce2a8d 100644 --- a/Providers/FreeSql.Provider.Firebird/FirebirdAdo/FirebirdConnectionPool.cs +++ b/Providers/FreeSql.Provider.Firebird/FirebirdAdo/FirebirdConnectionPool.cs @@ -55,7 +55,7 @@ class FirebirdConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.GBase/GBaseAdo/GBaseConnectionPool.cs b/Providers/FreeSql.Provider.GBase/GBaseAdo/GBaseConnectionPool.cs index 266eaa266..12d02f134 100644 --- a/Providers/FreeSql.Provider.GBase/GBaseAdo/GBaseConnectionPool.cs +++ b/Providers/FreeSql.Provider.GBase/GBaseAdo/GBaseConnectionPool.cs @@ -55,7 +55,7 @@ class GBaseConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.KingbaseES/KingbaseESAdo/KingbaseESConnectionPool.cs b/Providers/FreeSql.Provider.KingbaseES/KingbaseESAdo/KingbaseESConnectionPool.cs index 1a439a5b3..1cf74cb80 100644 --- a/Providers/FreeSql.Provider.KingbaseES/KingbaseESAdo/KingbaseESConnectionPool.cs +++ b/Providers/FreeSql.Provider.KingbaseES/KingbaseESAdo/KingbaseESConnectionPool.cs @@ -66,7 +66,7 @@ class KingbaseESConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.KingbaseES/KingbaseESDbFirst.cs b/Providers/FreeSql.Provider.KingbaseES/KingbaseESDbFirst.cs index b3a23d6cb..084eae7e3 100644 --- a/Providers/FreeSql.Provider.KingbaseES/KingbaseESDbFirst.cs +++ b/Providers/FreeSql.Provider.KingbaseES/KingbaseESDbFirst.cs @@ -67,7 +67,7 @@ KdbndpDbType GetSqlDbType(DbColumnInfo column) return ret; } - static ConcurrentDictionary _dicDbToCs = new ConcurrentDictionary(); + static ConcurrentDictionary _dicDbToCs = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); static KingbaseESDbFirst() { var defaultDbToCs = new Dictionary() { diff --git a/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlConnectionPool.cs b/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlConnectionPool.cs index e4488b584..f58ec2fad 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlConnectionPool.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlConnectionPool.cs @@ -59,7 +59,7 @@ class MySqlConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.MySqlConnector/MySqlConnectorUtils.cs b/Providers/FreeSql.Provider.MySqlConnector/MySqlConnectorUtils.cs index ad08572d5..e5246f9a8 100644 --- a/Providers/FreeSql.Provider.MySqlConnector/MySqlConnectorUtils.cs +++ b/Providers/FreeSql.Provider.MySqlConnector/MySqlConnectorUtils.cs @@ -74,7 +74,7 @@ public override DbParameter[] GetDbParamtersByObject(string sql, object obj) => return ret; }); - static ConcurrentDictionary> _dicEnumNames = new ConcurrentDictionary>(); + static ConcurrentDictionary> _dicEnumNames = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>()); static long EnumValueToMySql(object value) //mysqlConnector 不支持 enumString 作为参数化传递,所以要计算出下标值,mysql 下标从 1 开始,并且 c# 设置了枚举元素值会影响下标 { if (value == null) return 0; diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs index 9f8dd75a3..cbae5ad6d 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs @@ -66,7 +66,7 @@ class OdbcDamengConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengDbFirst.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengDbFirst.cs index 68e2f2a36..a3b629b34 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengDbFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengDbFirst.cs @@ -168,7 +168,7 @@ OdbcType GetSqlDbType(DbColumnInfo column) throw new NotImplementedException(CoreStrings.S_TypeMappingNotImplemented(column.DbTypeTextFull)); } - static ConcurrentDictionary _dicDbToCs = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary _dicDbToCs = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); static OdbcDamengDbFirst() { var defaultDbToCs = new Dictionary() { diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcConnectionPool.cs index ad43c4062..125e8dd0a 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcConnectionPool.cs @@ -55,7 +55,7 @@ class OdbcConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs index 152b5e018..526050991 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs @@ -91,7 +91,7 @@ public override void Dispose() partial class FreeSqlOdbcGlobalExtensions { internal static OdbcAdapter DefaultOdbcAdapter = new OdbcAdapter(); - internal static ConcurrentDictionary _dicOdbcAdater = new ConcurrentDictionary(); + internal static ConcurrentDictionary _dicOdbcAdater = Utils.GlobalCacheFactory.CreateCacheItem>(); public static void SetOdbcAdapter(this IFreeSql that, OdbcAdapter adapter) => _dicOdbcAdater.AddOrUpdate(that.Ado.Identifier, adapter, (fsql, old) => adapter); internal static OdbcAdapter GetOdbcAdapter(this IFreeSql that) => _dicOdbcAdater.TryGetValue(that.Ado.Identifier, out var tryada) ? tryada : DefaultOdbcAdapter; } diff --git a/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESAdo/OdbcKingbaseESConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESAdo/OdbcKingbaseESConnectionPool.cs index 9884b4b35..4831abb4c 100644 --- a/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESAdo/OdbcKingbaseESConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESAdo/OdbcKingbaseESConnectionPool.cs @@ -66,7 +66,7 @@ class OdbcKingbaseESConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESDbFirst.cs b/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESDbFirst.cs index 1f20cc6aa..616ded579 100644 --- a/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESDbFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESDbFirst.cs @@ -66,7 +66,7 @@ OdbcType GetSqlDbType(DbColumnInfo column) return ret; } - static ConcurrentDictionary _dicDbToCs = new ConcurrentDictionary(); + static ConcurrentDictionary _dicDbToCs = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); static OdbcKingbaseESDbFirst() { var defaultDbToCs = new Dictionary() { diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlConnectionPool.cs index ee2854e54..4978ad1d5 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlConnectionPool.cs @@ -55,7 +55,7 @@ class OdbcMySqlConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleConnectionPool.cs index 30bc350c5..3f8e3573c 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleConnectionPool.cs @@ -66,7 +66,7 @@ class OdbcOracleConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleDbFirst.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleDbFirst.cs index 8037ee9e8..b71d98312 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleDbFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleDbFirst.cs @@ -116,7 +116,7 @@ OdbcType GetSqlDbType(DbColumnInfo column) throw new NotImplementedException(CoreStrings.S_TypeMappingNotImplemented(column.DbTypeTextFull)); } - static ConcurrentDictionary _dicDbToCs = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary _dicDbToCs = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); static OdbcOracleDbFirst() { var defaultDbToCs = new Dictionary() { diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLConnectionPool.cs index b1797fba7..fe9c2a556 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLConnectionPool.cs @@ -56,7 +56,7 @@ class OdbcPostgreSQLConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerConnectionPool.cs index 9b2e0a3cd..d6f03cee2 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerConnectionPool.cs @@ -55,7 +55,7 @@ class OdbcSqlServerConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleConnectionPool.cs b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleConnectionPool.cs index 628a0a6f2..2f6c105e7 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleConnectionPool.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleConnectionPool.cs @@ -76,7 +76,7 @@ class OracleConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs b/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs index 98b7e57b6..a2a3ac7be 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs @@ -213,7 +213,7 @@ OracleDbType GetSqlDbType(DbColumnInfo column) } #endif - static ConcurrentDictionary _dicDbToCs = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary _dicDbToCs = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); static OracleDbFirst() { var defaultDbToCs = new Dictionary() { diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLConnectionPool.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLConnectionPool.cs index 890b9bcd6..c3fed1edc 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLConnectionPool.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLConnectionPool.cs @@ -56,7 +56,7 @@ class PostgreSQLConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLUtils.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLUtils.cs index 96ae3dfa3..8b3e13368 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLUtils.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLUtils.cs @@ -164,7 +164,7 @@ public override string TrimQuoteSqlName(string name) public override string QuoteWriteParamterAdapter(Type type, string paramterName) => paramterName; protected override string QuoteReadColumnAdapter(Type type, Type mapType, string columnName) => columnName; - static ConcurrentDictionary _dicIsAssignableFromPostgisGeometry = new ConcurrentDictionary(); + static ConcurrentDictionary _dicIsAssignableFromPostgisGeometry = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary()); public override string GetNoneParamaterSqlValue(List specialParams, string specialParamFlag, ColumnInfo col, Type type, object value) { if (value == null) return "NULL"; diff --git a/Providers/FreeSql.Provider.QuestDb/QuestDbAdo/QuestDbConnectionPool.cs b/Providers/FreeSql.Provider.QuestDb/QuestDbAdo/QuestDbConnectionPool.cs index 8308c677d..5d1386281 100644 --- a/Providers/FreeSql.Provider.QuestDb/QuestDbAdo/QuestDbConnectionPool.cs +++ b/Providers/FreeSql.Provider.QuestDb/QuestDbAdo/QuestDbConnectionPool.cs @@ -56,7 +56,7 @@ class QuestDbConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.ShenTong/ShenTongAdo/ShenTongConnectionPool.cs b/Providers/FreeSql.Provider.ShenTong/ShenTongAdo/ShenTongConnectionPool.cs index c7f8ab7f4..9212a07a9 100644 --- a/Providers/FreeSql.Provider.ShenTong/ShenTongAdo/ShenTongConnectionPool.cs +++ b/Providers/FreeSql.Provider.ShenTong/ShenTongAdo/ShenTongConnectionPool.cs @@ -54,7 +54,7 @@ class ShenTongConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerConnectionPool.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerConnectionPool.cs index dc75463ae..211e6a14f 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerConnectionPool.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerConnectionPool.cs @@ -59,7 +59,7 @@ class SqlServerConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs index 27bd0bb63..7ed18bf58 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs @@ -134,7 +134,7 @@ public static IFreeSql SetGlobalSelectWithLock(this IFreeSql that, SqlServerLock _dicSetGlobalSelectWithLock.AddOrUpdate(that.Ado.Identifier, value, (_, __) => value); return that; } - internal static ConcurrentDictionary>> _dicSetGlobalSelectWithLock = new ConcurrentDictionary>>(); + internal static ConcurrentDictionary>> _dicSetGlobalSelectWithLock = FreeSql.Internal.Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary>>()); #region ExecuteSqlBulkCopy /// @@ -416,7 +416,7 @@ async public static Task ExecuteSqlBulkCopyAsync(this IInsert that, SqlBul } } #endif -#endregion + #endregion } [Flags] diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteDbFirst.cs b/Providers/FreeSql.Provider.Sqlite/SqliteDbFirst.cs index 0084a7fc3..72d7070e8 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteDbFirst.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteDbFirst.cs @@ -105,7 +105,7 @@ DbType GetSqlDbType(DbColumnInfo column) throw new NotImplementedException(CoreStrings.S_TypeMappingNotImplemented(column.DbTypeTextFull)); } - static ConcurrentDictionary _dicDbToCs = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary _dicDbToCs = Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); static SqliteDbFirst() { var defaultDbToCs = new Dictionary() { diff --git a/Providers/FreeSql.Provider.Xugu/XuguAdo/XuguConnectionPool.cs b/Providers/FreeSql.Provider.Xugu/XuguAdo/XuguConnectionPool.cs index e5d4ec117..8e11ad632 100644 --- a/Providers/FreeSql.Provider.Xugu/XuguAdo/XuguConnectionPool.cs +++ b/Providers/FreeSql.Provider.Xugu/XuguAdo/XuguConnectionPool.cs @@ -53,7 +53,7 @@ class XuguConnectionPoolPolicy : IPolicy public int CheckAvailableInterval { get; set; } = 2; public int Weight { get; set; } = 1; - static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static ConcurrentDictionary dicConnStrIncr =FreeSql.Internal. Utils.GlobalCacheFactory.CreateCacheItem(new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase)); private string _connectionString; public string ConnectionString { diff --git a/Providers/FreeSql.Provider.Xugu/XuguUtils.cs b/Providers/FreeSql.Provider.Xugu/XuguUtils.cs index fc16dc158..c44072697 100644 --- a/Providers/FreeSql.Provider.Xugu/XuguUtils.cs +++ b/Providers/FreeSql.Provider.Xugu/XuguUtils.cs @@ -55,16 +55,16 @@ public override string QuoteSqlNameAdapter(params string[] name) { typeof(ushort).FullName, a => int.Parse(string.Concat(a)) }, { typeof(ushort[]).FullName, a => getParamterArrayValue(typeof(int), a, 0) }, { typeof(ushort?[]).FullName, a => getParamterArrayValue(typeof(int?), a, null) }, { typeof(byte).FullName, a => short.Parse(string.Concat(a)) }, { typeof(byte[]).FullName, a => getParamterArrayValue(typeof(short), a, 0) }, { typeof(byte?[]).FullName, a => getParamterArrayValue(typeof(short?), a, null) }, { typeof(sbyte).FullName, a => short.Parse(string.Concat(a)) }, { typeof(sbyte[]).FullName, a => getParamterArrayValue(typeof(short), a, 0) }, { typeof(sbyte?[]).FullName, a => getParamterArrayValue(typeof(short?), a, null) }, - { typeof(char).FullName, a => string.Concat(a).Replace('\0', ' ').ToCharArray().FirstOrDefault() }, + { typeof(char).FullName, a => string.Concat(a).Replace('\0', ' ').ToCharArray().FirstOrDefault() }, { typeof(BigInteger).FullName, a => BigInteger.Parse(string.Concat(a), System.Globalization.NumberStyles.Any) }, { typeof(BigInteger[]).FullName, a => getParamterArrayValue(typeof(BigInteger), a, 0) }, { typeof(BigInteger?[]).FullName, a => getParamterArrayValue(typeof(BigInteger?), a, null) }, - + { typeof((IPAddress Address, int Subnet)).FullName, a => { var inet = ((IPAddress Address, int Subnet))a; if (inet.Address == null) return (IPAddress.Any, inet.Subnet); return inet; - } }, - { typeof((IPAddress Address, int Subnet)[]).FullName, a => getParamterArrayValue(typeof((IPAddress Address, int Subnet)), a, (IPAddress.Any, 0)) }, + } }, + { typeof((IPAddress Address, int Subnet)[]).FullName, a => getParamterArrayValue(typeof((IPAddress Address, int Subnet)), a, (IPAddress.Any, 0)) }, { typeof((IPAddress Address, int Subnet)?[]).FullName, a => getParamterArrayValue(typeof((IPAddress Address, int Subnet)?), a, null) }, }; static object getParamterValue(Type type, object value, int level = 0) @@ -93,17 +93,17 @@ public override DbParameter AppendParamter(List _params, string par if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}"; if (value != null) value = getParamterValue(type, value); var ret = new XGParameters { ParameterName = parameterName, Value = value }; - - var tp = _orm.CodeFirst.GetDbInfo(type)?.type; + + var tp = _orm.CodeFirst.GetDbInfo(type)?.type; if (col != null) { var dbtype = (XGDbType?)_orm.DbFirst.GetDbType(new DatabaseModel.DbColumnInfo { DbTypeText = col.DbTypeText }); if (dbtype != null) - { + { if (col.DbPrecision != 0) ret.Precision = col.DbPrecision; if (col.DbScale != 0) ret.Scale = col.DbScale; } - } + } _params?.Add(ret); return ret; } @@ -113,14 +113,14 @@ public override DbParameter[] GetDbParamtersByObject(string sql, object obj) => { if (value != null) value = getParamterValue(type, value); var ret = new XGParameters { ParameterName = name, Value = value }; - + var tp = _orm.CodeFirst.GetDbInfo(type)?.type; - + return ret; }); public override string FormatSql(string sql, params object[] args) => sql?.FormatXuguSQL(args); - + public override string TrimQuoteSqlName(string name) { var nametrim = name.Trim(); @@ -140,12 +140,12 @@ public override string TrimQuoteSqlName(string name) public override string QuoteWriteParamterAdapter(Type type, string paramterName) => paramterName; protected override string QuoteReadColumnAdapter(Type type, Type mapType, string columnName) => columnName; - static ConcurrentDictionary _dicIsAssignableFromPostgisGeometry = new ConcurrentDictionary(); + static ConcurrentDictionary _dicIsAssignableFromPostgisGeometry = Utils.GlobalCacheFactory.CreateCacheItem>(); public override string GetNoneParamaterSqlValue(List specialParams, string specialParamFlag, ColumnInfo col, Type type, object value) { if (value == null) return "NULL"; if (type.IsNumberType()) return string.Format(CultureInfo.InvariantCulture, "{0}", value); - + value = getParamterValue(type, value); var type2 = value.GetType(); if (type2 == typeof(byte[])) return $"'\\x{CommonUtils.BytesSqlRaw(value as byte[])}'";