fix: 修复实体对象无空构造函数时通过Repository操作引发异常的问题,增加Lazy改进并发

This commit is contained in:
xuna 2022-07-26 20:06:26 +08:00
parent aba2e14c5d
commit c33d8c6d39
5 changed files with 18 additions and 13 deletions

View File

@ -219,7 +219,7 @@ namespace FreeSql
public DbSet<TEntity> AttachOnlyPrimary(TEntity data) public DbSet<TEntity> AttachOnlyPrimary(TEntity data)
{ {
if (data == null) return this; if (data == null) return this;
var pkitem = (TEntity)Activator.CreateInstance(_entityType); var pkitem = (TEntity)_entityType.CreateInstanceGetDefaultValue();
foreach (var pk in _db.OrmOriginal.CodeFirst.GetTableByEntity(_entityType).Primarys) foreach (var pk in _db.OrmOriginal.CodeFirst.GetTableByEntity(_entityType).Primarys)
{ {
var colVal = _db.OrmOriginal.GetEntityValueWithPropertyName(_entityType, data, pk.CsName); var colVal = _db.OrmOriginal.GetEntityValueWithPropertyName(_entityType, data, pk.CsName);
@ -267,8 +267,8 @@ namespace FreeSql
{ {
if (data == null) throw new ArgumentNullException(nameof(data)); if (data == null) throw new ArgumentNullException(nameof(data));
var key = _db.OrmOriginal.GetEntityKeyString(_entityType, data, false); var key = _db.OrmOriginal.GetEntityKeyString(_entityType, data, false);
var state = new EntityState((TEntity)Activator.CreateInstance(_entityType), key); var state = new EntityState((TEntity)_entityType.CreateInstanceGetDefaultValue(), key);
_db.OrmOriginal.MapEntityValue(_entityType, data, state.Value); _db.OrmOriginal.MapEntityValue(_entityType, data, state.Value);
return state; return state;
} }
bool? ExistsInStates(TEntity data) bool? ExistsInStates(TEntity data)

View File

@ -312,7 +312,7 @@ namespace FreeSql
midSet.RemoveRange(midListDel); //删除未保存的项 midSet.RemoveRange(midListDel); //删除未保存的项
foreach (var curItem in curList) foreach (var curItem in curList)
{ {
var newItem = Activator.CreateInstance(tref.RefMiddleEntityType); var newItem = tref.RefMiddleEntityType.CreateInstanceGetDefaultValue();
for (var colidx = 0; colidx < tref.Columns.Count; colidx++) for (var colidx = 0; colidx < tref.Columns.Count; colidx++)
{ {
var val = FreeSql.Internal.Utils.GetDataReaderValue(tref.MiddleColumns[colidx].CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)); var val = FreeSql.Internal.Utils.GetDataReaderValue(tref.MiddleColumns[colidx].CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName));

View File

@ -323,7 +323,7 @@ namespace FreeSql
midSet.RemoveRange(midListDel); //删除未保存的项 midSet.RemoveRange(midListDel); //删除未保存的项
foreach (var curItem in curList) foreach (var curItem in curList)
{ {
var newItem = Activator.CreateInstance(tref.RefMiddleEntityType); var newItem = tref.RefMiddleEntityType.CreateInstanceGetDefaultValue();
for (var colidx = 0; colidx < tref.Columns.Count; colidx++) for (var colidx = 0; colidx < tref.Columns.Count; colidx++)
{ {
var val = FreeSql.Internal.Utils.GetDataReaderValue(tref.MiddleColumns[colidx].CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)); var val = FreeSql.Internal.Utils.GetDataReaderValue(tref.MiddleColumns[colidx].CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName));

View File

@ -197,7 +197,7 @@ namespace FreeSql
var tb = _db.OrmOriginal.CodeFirst.GetTableByEntity(EntityType); var tb = _db.OrmOriginal.CodeFirst.GetTableByEntity(EntityType);
if (tb.Primarys.Length != 1) throw new Exception(DbContextStrings.EntityType_PrimaryKeyIsNotOne(EntityType.Name)); if (tb.Primarys.Length != 1) throw new Exception(DbContextStrings.EntityType_PrimaryKeyIsNotOne(EntityType.Name));
if (tb.Primarys[0].CsType.NullableTypeOrThis() != typeof(TKey).NullableTypeOrThis()) throw new Exception(DbContextStrings.EntityType_PrimaryKeyError(EntityType.Name, typeof(TKey).FullName)); if (tb.Primarys[0].CsType.NullableTypeOrThis() != typeof(TKey).NullableTypeOrThis()) throw new Exception(DbContextStrings.EntityType_PrimaryKeyError(EntityType.Name, typeof(TKey).FullName));
var obj = Activator.CreateInstance(tb.Type); var obj = tb.Type.CreateInstanceGetDefaultValue();
_db.OrmOriginal.SetEntityValueWithPropertyName(tb.Type, obj, tb.Primarys[0].CsName, id); _db.OrmOriginal.SetEntityValueWithPropertyName(tb.Type, obj, tb.Primarys[0].CsName, id);
var ret = obj as TEntity; var ret = obj as TEntity;
if (ret == null) throw new Exception(DbContextStrings.EntityType_CannotConvert(EntityType.Name, typeof(TEntity).Name)); if (ret == null) throw new Exception(DbContextStrings.EntityType_CannotConvert(EntityType.Name, typeof(TEntity).Name));

View File

@ -151,14 +151,19 @@ public static partial class FreeSqlGlobalExtensions
return Expression.New(ctor, ctor.GetParameters().Select(a => Expression.Constant(a.ParameterType.CreateInstanceGetDefaultValue(), a.ParameterType))); return Expression.New(ctor, ctor.GetParameters().Select(a => Expression.Constant(a.ParameterType.CreateInstanceGetDefaultValue(), a.ParameterType)));
} }
static ConcurrentDictionary<Type, ConstructorInfo> _dicInternalGetTypeConstructor0OrFirst = new ConcurrentDictionary<Type, ConstructorInfo>(); static ConcurrentDictionary<Type, Lazy<ConstructorInfo>> _dicInternalGetTypeConstructor0OrFirst = new ConcurrentDictionary<Type, Lazy<ConstructorInfo>>();
internal static ConstructorInfo InternalGetTypeConstructor0OrFirst(this Type that, bool isThrow = true) internal static ConstructorInfo InternalGetTypeConstructor0OrFirst(this Type that, bool isThrow = true)
{ {
var ret = _dicInternalGetTypeConstructor0OrFirst.GetOrAdd(that, tp => var ret = _dicInternalGetTypeConstructor0OrFirst.GetOrAdd(that, tp =>
tp.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null) ?? new Lazy<ConstructorInfo>(() =>
tp.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).OrderBy(a => a.IsPublic ? 0 : 1).FirstOrDefault()); {
if (ret == null && isThrow) throw new ArgumentException(CoreStrings.Type_Cannot_Access_Constructor(that.FullName)); return tp.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null) ??
return ret; tp.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.OrderBy(a => a.IsPublic ? 0 : 1)
.FirstOrDefault();
}));
if (ret.Value == null && isThrow) throw new ArgumentException(CoreStrings.Type_Cannot_Access_Constructor(that.FullName));
return ret.Value;
} }
static ConcurrentDictionary<Type, Dictionary<string, PropertyInfo>> _dicGetPropertiesDictIgnoreCase = new ConcurrentDictionary<Type, Dictionary<string, PropertyInfo>>(); static ConcurrentDictionary<Type, Dictionary<string, PropertyInfo>> _dicGetPropertiesDictIgnoreCase = new ConcurrentDictionary<Type, Dictionary<string, PropertyInfo>>();
@ -466,7 +471,7 @@ public static partial class FreeSqlGlobalExtensions
if (keyval.Length != 2) throw new ArgumentException(CoreStrings.ParameterError_NotValid_UseCommas(nameof(where))); if (keyval.Length != 2) throw new ArgumentException(CoreStrings.ParameterError_NotValid_UseCommas(nameof(where)));
if (reftb.ColumnsByCs.TryGetValue(keyval[0], out var keycol) == false) if (reftb.ColumnsByCs.TryGetValue(keyval[0], out var keycol) == false)
throw new ArgumentException(CoreStrings.ParameterError_NotValid_PropertyName(nameof(where),keyval[0], reftb.Type.DisplayCsharp())); throw new ArgumentException(CoreStrings.ParameterError_NotValid_PropertyName(nameof(where), keyval[0], reftb.Type.DisplayCsharp()));
if (parTb.ColumnsByCs.TryGetValue(keyval[1], out var valcol) == false) if (parTb.ColumnsByCs.TryGetValue(keyval[1], out var valcol) == false)
throw new ArgumentException(CoreStrings.ParameterError_NotValid_PropertyName(nameof(where), keyval[1], parTb.Type.DisplayCsharp())); throw new ArgumentException(CoreStrings.ParameterError_NotValid_PropertyName(nameof(where), keyval[1], parTb.Type.DisplayCsharp()));
@ -1210,5 +1215,5 @@ SELECT ");
#endregion #endregion
} }