- 优化 DbContext/Repository Orm 属性进行 CURD 与自身事务相同【新突破】;#270

This commit is contained in:
28810 2020-04-10 19:54:43 +08:00
parent d97dc3383c
commit 52fbe5ed86
17 changed files with 3884 additions and 3849 deletions

View File

@ -10,13 +10,9 @@ namespace FreeSql
{ {
public abstract partial class DbContext : IDisposable public abstract partial class DbContext : IDisposable
{ {
internal IFreeSql _ormPriv; internal DbContextScopedFreeSql _ormScoped;
internal IFreeSql OrmOriginal => _ormScoped?._originalFsql ?? throw new ArgumentNullException("请在 OnConfiguring 或 AddFreeDbContext 中配置 UseFreeSql");
/// <summary> public IFreeSql Orm => _ormScoped ?? throw new ArgumentNullException("请在 OnConfiguring 或 AddFreeDbContext 中配置 UseFreeSql");
/// 注意IFreeSql 属于顶级对象,事务无法自动传递。<para></para>
/// 手工传递事务ISelect/IInsert/IDelete/IUpdate 可以使用 WithTransaction(uow.GetOrBeginTransaction())
/// </summary>
public IFreeSql Orm => _ormPriv ?? throw new ArgumentNullException("请在 OnConfiguring 或 AddFreeDbContext 中配置 UseFreeSql");
#region Property UnitOfWork #region Property UnitOfWork
internal bool _isUseUnitOfWork = true; //是否创建工作单元事务 internal bool _isUseUnitOfWork = true; //是否创建工作单元事务
@ -28,7 +24,7 @@ namespace FreeSql
{ {
if (_uowPriv != null) return _uowPriv; if (_uowPriv != null) return _uowPriv;
if (_isUseUnitOfWork == false) return null; if (_isUseUnitOfWork == false) return null;
return _uowPriv = new UnitOfWork(Orm); return _uowPriv = new UnitOfWork(OrmOriginal);
} }
} }
#endregion #endregion
@ -43,7 +39,7 @@ namespace FreeSql
if (_optionsPriv == null) if (_optionsPriv == null)
{ {
_optionsPriv = new DbContextOptions(); _optionsPriv = new DbContextOptions();
if (FreeSqlDbContextExtensions._dicSetDbContextOptions.TryGetValue(Orm.Ado.Identifier, out var opt)) if (FreeSqlDbContextExtensions._dicSetDbContextOptions.TryGetValue(OrmOriginal.Ado.Identifier, out var opt))
{ {
_optionsPriv.EnableAddOrUpdateNavigateList = opt.EnableAddOrUpdateNavigateList; _optionsPriv.EnableAddOrUpdateNavigateList = opt.EnableAddOrUpdateNavigateList;
_optionsPriv.OnEntityChange = opt.OnEntityChange; _optionsPriv.OnEntityChange = opt.OnEntityChange;
@ -63,17 +59,17 @@ namespace FreeSql
protected DbContext() : this(null, null) { } protected DbContext() : this(null, null) { }
protected DbContext(IFreeSql fsql, DbContextOptions options) protected DbContext(IFreeSql fsql, DbContextOptions options)
{ {
_ormPriv = fsql; _ormScoped = DbContextScopedFreeSql.Create(fsql, () => this, () => UnitOfWork);
_optionsPriv = options; _optionsPriv = options;
if (_ormPriv == null) if (_ormScoped == null)
{ {
var builder = new DbContextOptionsBuilder(); var builder = new DbContextOptionsBuilder();
OnConfiguring(builder); OnConfiguring(builder);
_ormPriv = builder._fsql; _ormScoped = DbContextScopedFreeSql.Create(builder._fsql, () => this, () => UnitOfWork);
_optionsPriv = builder._options; _optionsPriv = builder._options;
} }
if (_ormPriv != null) InitPropSets(); if (_ormScoped != null) InitPropSets();
} }
protected virtual void OnConfiguring(DbContextOptionsBuilder builder) { } protected virtual void OnConfiguring(DbContextOptionsBuilder builder) { }
@ -113,7 +109,7 @@ namespace FreeSql
#region DbSet #region DbSet
void CheckEntityTypeOrThrow(Type entityType) void CheckEntityTypeOrThrow(Type entityType)
{ {
if (Orm.CodeFirst.GetTableByEntity(entityType) == null) if (OrmOriginal.CodeFirst.GetTableByEntity(entityType) == null)
throw new ArgumentException($"参数 data 类型错误 {entityType.FullName} "); throw new ArgumentException($"参数 data 类型错误 {entityType.FullName} ");
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,74 @@
using FreeSql;
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
namespace FreeSql
{
class DbContextScopedFreeSql : IFreeSql
{
public IFreeSql _originalFsql;
Func<DbContext> _resolveDbContext;
Func<IUnitOfWork> _resolveUnitOfWork;
DbContextScopedFreeSql() { }
public static DbContextScopedFreeSql Create(IFreeSql fsql, Func<DbContext> resolveDbContext, Func<IUnitOfWork> resolveUnitOfWork)
{
if (fsql == null) return null;
var scopedfsql = fsql as DbContextScopedFreeSql;
if (scopedfsql == null) return new DbContextScopedFreeSql { _originalFsql = fsql, _resolveDbContext = resolveDbContext, _resolveUnitOfWork = resolveUnitOfWork };
return Create(scopedfsql._originalFsql, resolveDbContext, resolveUnitOfWork);
}
public IAdo Ado => _originalFsql.Ado;
public IAop Aop => _originalFsql.Aop;
public ICodeFirst CodeFirst => _originalFsql.CodeFirst;
public IDbFirst DbFirst => _originalFsql.DbFirst;
public GlobalFilter GlobalFilter => _originalFsql.GlobalFilter;
public void Dispose() { }
public void Transaction(Action handler) => _originalFsql.Transaction(handler);
public void Transaction(TimeSpan timeout, Action handler) => _originalFsql.Transaction(timeout, handler);
public void Transaction(IsolationLevel isolationLevel, TimeSpan timeout, Action handler) => _originalFsql.Transaction(isolationLevel, timeout, handler);
public ISelect<T1> Select<T1>() where T1 : class
{
_resolveDbContext()?.ExecCommand();
return _originalFsql.Select<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction(false));
}
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => Select<T1>().WhereDynamic(dywhere);
public IDelete<T1> Delete<T1>() where T1 : class
{
_resolveDbContext()?.ExecCommand();
return _originalFsql.Delete<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
}
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => Delete<T1>().WhereDynamic(dywhere);
public IUpdate<T1> Update<T1>() where T1 : class
{
var db = _resolveDbContext();
db?.ExecCommand();
var update = _originalFsql.Update<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
if (db?.Options.NoneParameter != null) update.NoneParameter(db.Options.NoneParameter.Value);
return update;
}
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => Update<T1>().WhereDynamic(dywhere);
public IInsert<T1> Insert<T1>() where T1 : class
{
var db = _resolveDbContext();
db?.ExecCommand();
var insert = _originalFsql.Insert<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
if (db?.Options.NoneParameter != null) insert.NoneParameter(db.Options.NoneParameter.Value);
return insert;
}
public IInsert<T1> Insert<T1>(T1 source) where T1 : class => Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(T1[] source) where T1 : class => Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(List<T1> source) where T1 : class => Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class => Insert<T1>().AppendData(source);
}
}

View File

@ -7,7 +7,7 @@ namespace FreeSql
public FreeContext(IFreeSql orm) public FreeContext(IFreeSql orm)
{ {
_ormPriv = orm; _ormScoped = DbContextScopedFreeSql.Create(orm, () => this, () => UnitOfWork);
} }
} }
} }

View File

@ -33,7 +33,7 @@ namespace FreeSql
protected virtual ISelect<TEntity> OrmSelect(object dywhere) protected virtual ISelect<TEntity> OrmSelect(object dywhere)
{ {
DbContextExecCommand(); //查询前先提交,否则会出脏读 DbContextExecCommand(); //查询前先提交,否则会出脏读
return _db.Orm.Select<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction(false)).TrackToList(TrackToList).WhereDynamic(dywhere); return _db.OrmOriginal.Select<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction(false)).TrackToList(TrackToList).WhereDynamic(dywhere);
} }
~DbSet() => this.Dispose(); ~DbSet() => this.Dispose();
@ -54,7 +54,7 @@ namespace FreeSql
protected virtual IInsert<TEntity> OrmInsert() protected virtual IInsert<TEntity> OrmInsert()
{ {
var insert = _db.Orm.Insert<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction()); var insert = _db.OrmOriginal.Insert<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction());
if (_db.Options.NoneParameter != null) insert.NoneParameter(_db.Options.NoneParameter.Value); if (_db.Options.NoneParameter != null) insert.NoneParameter(_db.Options.NoneParameter.Value);
return insert; return insert;
} }
@ -63,11 +63,11 @@ namespace FreeSql
protected virtual IUpdate<TEntity> OrmUpdate(IEnumerable<TEntity> entitys) protected virtual IUpdate<TEntity> OrmUpdate(IEnumerable<TEntity> entitys)
{ {
var update = _db.Orm.Update<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction()); var update = _db.OrmOriginal.Update<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction());
if (_db.Options.NoneParameter != null) update.NoneParameter(_db.Options.NoneParameter.Value); if (_db.Options.NoneParameter != null) update.NoneParameter(_db.Options.NoneParameter.Value);
return update.SetSource(entitys); return update.SetSource(entitys);
} }
protected virtual IDelete<TEntity> OrmDelete(object dywhere) => _db.Orm.Delete<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction()).WhereDynamic(dywhere); protected virtual IDelete<TEntity> OrmDelete(object dywhere) => _db.OrmOriginal.Delete<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction()).WhereDynamic(dywhere);
internal void EnqueueToDbContext(DbContext.EntityChangeType changeType, EntityState state) => internal void EnqueueToDbContext(DbContext.EntityChangeType changeType, EntityState state) =>
_db.EnqueueAction(changeType, this, typeof(EntityState), _entityType, state); _db.EnqueueAction(changeType, this, typeof(EntityState), _entityType, state);
@ -89,7 +89,7 @@ namespace FreeSql
var itemType = item.GetType(); var itemType = item.GetType();
if (itemType == typeof(object)) return; if (itemType == typeof(object)) return;
if (itemType.FullName.Contains("FreeSqlLazyEntity__")) itemType = itemType.BaseType; if (itemType.FullName.Contains("FreeSqlLazyEntity__")) itemType = itemType.BaseType;
if (_db.Orm.CodeFirst.GetTableByEntity(itemType)?.Primarys.Any() != true) return; if (_db.OrmOriginal.CodeFirst.GetTableByEntity(itemType)?.Primarys.Any() != true) return;
var dbset = _db.Set(itemType); var dbset = _db.Set(itemType);
dbset?.GetType().GetMethod("TrackToList", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(dbset, new object[] { list }); dbset?.GetType().GetMethod("TrackToList", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(dbset, new object[] { list });
return; return;
@ -99,11 +99,11 @@ namespace FreeSql
if (_table?.Primarys.Any() != true) return; if (_table?.Primarys.Any() != true) return;
foreach (var item in ls) foreach (var item in ls)
{ {
var key = _db.Orm.GetEntityKeyString(_entityType, item, false); var key = _db.OrmOriginal.GetEntityKeyString(_entityType, item, false);
if (key == null) continue; if (key == null) continue;
_states.AddOrUpdate(key, k => CreateEntityState(item), (k, ov) => _states.AddOrUpdate(key, k => CreateEntityState(item), (k, ov) =>
{ {
_db.Orm.MapEntityValue(_entityType, item, ov.Value); _db.OrmOriginal.MapEntityValue(_entityType, item, ov.Value);
ov.Time = DateTime.Now; ov.Time = DateTime.Now;
return ov; return ov;
}); });
@ -117,7 +117,7 @@ namespace FreeSql
protected ConcurrentDictionary<string, EntityState> _states = new ConcurrentDictionary<string, EntityState>(); protected ConcurrentDictionary<string, EntityState> _states = new ConcurrentDictionary<string, EntityState>();
internal ConcurrentDictionary<string, EntityState> _statesInternal => _states; internal ConcurrentDictionary<string, EntityState> _statesInternal => _states;
TableInfo _tablePriv; TableInfo _tablePriv;
protected TableInfo _table => _tablePriv ?? (_tablePriv = _db.Orm.CodeFirst.GetTableByEntity(_entityType)); protected TableInfo _table => _tablePriv ?? (_tablePriv = _db.OrmOriginal.CodeFirst.GetTableByEntity(_entityType));
ColumnInfo[] _tableIdentitysPriv, _tableServerTimesPriv; ColumnInfo[] _tableIdentitysPriv, _tableServerTimesPriv;
protected ColumnInfo[] _tableIdentitys => _tableIdentitysPriv ?? (_tableIdentitysPriv = _table.Primarys.Where(a => a.Attribute.IsIdentity).ToArray()); protected ColumnInfo[] _tableIdentitys => _tableIdentitysPriv ?? (_tableIdentitysPriv = _table.Primarys.Where(a => a.Attribute.IsIdentity).ToArray());
protected ColumnInfo[] _tableServerTimes => _tableServerTimesPriv ?? (_tableServerTimesPriv = _table.Primarys.Where(a => a.Attribute.ServerTime != DateTimeKind.Unspecified).ToArray()); protected ColumnInfo[] _tableServerTimes => _tableServerTimesPriv ?? (_tableServerTimesPriv = _table.Primarys.Where(a => a.Attribute.ServerTime != DateTimeKind.Unspecified).ToArray());
@ -133,7 +133,7 @@ namespace FreeSql
{ {
if (entityType == typeof(object)) throw new Exception("ISelect.AsType 参数不支持指定为 object"); if (entityType == typeof(object)) throw new Exception("ISelect.AsType 参数不支持指定为 object");
if (entityType == _entityType) return this; if (entityType == _entityType) return this;
var newtb = _db.Orm.CodeFirst.GetTableByEntity(entityType); var newtb = _db.OrmOriginal.CodeFirst.GetTableByEntity(entityType);
_entityType = entityType; _entityType = entityType;
_tablePriv = newtb ?? throw new Exception("DbSet.AsType 参数错误,请传入正确的实体类型"); _tablePriv = newtb ?? throw new Exception("DbSet.AsType 参数错误,请传入正确的实体类型");
_tableIdentitysPriv = null; _tableIdentitysPriv = null;
@ -179,15 +179,15 @@ namespace FreeSql
public void AttachRange(IEnumerable<TEntity> data) public void AttachRange(IEnumerable<TEntity> data)
{ {
if (data == null || data.Any() == false) return; if (data == null || data.Any() == false) return;
if (_table.Primarys.Any() == false) throw new Exception($"不可附加,实体没有主键:{_db.Orm.GetEntityString(_entityType, data.First())}"); if (_table.Primarys.Any() == false) throw new Exception($"不可附加,实体没有主键:{_db.OrmOriginal.GetEntityString(_entityType, data.First())}");
foreach (var item in data) foreach (var item in data)
{ {
var key = _db.Orm.GetEntityKeyString(_entityType, item, false); var key = _db.OrmOriginal.GetEntityKeyString(_entityType, item, false);
if (string.IsNullOrEmpty(key)) throw new Exception($"不可附加,未设置主键的值:{_db.Orm.GetEntityString(_entityType, item)}"); if (string.IsNullOrEmpty(key)) throw new Exception($"不可附加,未设置主键的值:{_db.OrmOriginal.GetEntityString(_entityType, item)}");
_states.AddOrUpdate(key, k => CreateEntityState(item), (k, ov) => _states.AddOrUpdate(key, k => CreateEntityState(item), (k, ov) =>
{ {
_db.Orm.MapEntityValue(_entityType, item, ov.Value); _db.OrmOriginal.MapEntityValue(_entityType, item, ov.Value);
ov.Time = DateTime.Now; ov.Time = DateTime.Now;
return ov; return ov;
}); });
@ -201,10 +201,10 @@ namespace FreeSql
{ {
if (data == null) return this; if (data == null) return this;
var pkitem = (TEntity)Activator.CreateInstance(_entityType); var pkitem = (TEntity)Activator.CreateInstance(_entityType);
foreach (var pk in _db.Orm.CodeFirst.GetTableByEntity(_entityType).Primarys) foreach (var pk in _db.OrmOriginal.CodeFirst.GetTableByEntity(_entityType).Primarys)
{ {
var colVal = _db.Orm.GetEntityValueWithPropertyName(_entityType, data, pk.CsName); var colVal = _db.OrmOriginal.GetEntityValueWithPropertyName(_entityType, data, pk.CsName);
_db.Orm.SetEntityValueWithPropertyName(_entityType, pkitem, pk.CsName, colVal); _db.OrmOriginal.SetEntityValueWithPropertyName(_entityType, pkitem, pk.CsName, colVal);
} }
this.Attach(pkitem); this.Attach(pkitem);
return this; return this;
@ -222,15 +222,15 @@ namespace FreeSql
EntityState CreateEntityState(TEntity data) EntityState CreateEntityState(TEntity data)
{ {
if (data == null) throw new ArgumentNullException(nameof(data)); if (data == null) throw new ArgumentNullException(nameof(data));
var key = _db.Orm.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)Activator.CreateInstance(_entityType), key);
_db.Orm.MapEntityValue(_entityType, data, state.Value); _db.OrmOriginal.MapEntityValue(_entityType, data, state.Value);
return state; return state;
} }
bool? ExistsInStates(TEntity data) bool? ExistsInStates(TEntity data)
{ {
if (data == null) throw new ArgumentNullException(nameof(data)); if (data == null) throw new ArgumentNullException(nameof(data));
var key = _db.Orm.GetEntityKeyString(_entityType, data, false); var key = _db.OrmOriginal.GetEntityKeyString(_entityType, data, false);
if (string.IsNullOrEmpty(key)) return null; if (string.IsNullOrEmpty(key)) return null;
return _states.ContainsKey(key); return _states.ContainsKey(key);
} }
@ -255,14 +255,14 @@ namespace FreeSql
} }
if (_table.Primarys.Any() == false) if (_table.Primarys.Any() == false)
{ {
if (isThrow) throw new Exception($"不可添加,实体没有主键:{_db.Orm.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可添加,实体没有主键:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
FreeSql.Internal.CommonProvider.InsertProvider<TEntity>.AuditDataValue(this, data, _db.Orm, _table, null); FreeSql.Internal.CommonProvider.InsertProvider<TEntity>.AuditDataValue(this, data, _db.OrmOriginal, _table, null);
var key = _db.Orm.GetEntityKeyString(_entityType, data, true); var key = _db.OrmOriginal.GetEntityKeyString(_entityType, data, true);
if (string.IsNullOrEmpty(key)) if (string.IsNullOrEmpty(key))
{ {
switch (_db.Orm.Ado.DataType) switch (_db.OrmOriginal.Ado.DataType)
{ {
case DataType.SqlServer: case DataType.SqlServer:
case DataType.OdbcSqlServer: case DataType.OdbcSqlServer:
@ -272,7 +272,7 @@ namespace FreeSql
default: default:
if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1) if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1)
return true; return true;
if (isThrow) throw new Exception($"不可添加,未设置主键的值:{_db.Orm.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可添加,未设置主键的值:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
} }
@ -280,13 +280,13 @@ namespace FreeSql
{ {
if (_states.ContainsKey(key)) if (_states.ContainsKey(key))
{ {
if (isThrow) throw new Exception($"不可添加,已存在于状态管理:{_db.Orm.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可添加,已存在于状态管理:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
var idval = _db.Orm.GetEntityIdentityValueWithPrimary(_entityType, data); var idval = _db.OrmOriginal.GetEntityIdentityValueWithPrimary(_entityType, data);
if (idval > 0) if (idval > 0)
{ {
if (isThrow) throw new Exception($"不可添加,自增属性有值:{_db.Orm.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可添加,自增属性有值:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
} }
@ -313,19 +313,19 @@ namespace FreeSql
} }
if (_table.Primarys.Any() == false) if (_table.Primarys.Any() == false)
{ {
if (isThrow) throw new Exception($"不可更新,实体没有主键:{_db.Orm.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可更新,实体没有主键:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
FreeSql.Internal.CommonProvider.UpdateProvider<TEntity>.AuditDataValue(this, data, _db.Orm, _table, null); FreeSql.Internal.CommonProvider.UpdateProvider<TEntity>.AuditDataValue(this, data, _db.OrmOriginal, _table, null);
var key = _db.Orm.GetEntityKeyString(_entityType, data, false); var key = _db.OrmOriginal.GetEntityKeyString(_entityType, data, false);
if (string.IsNullOrEmpty(key)) if (string.IsNullOrEmpty(key))
{ {
if (isThrow) throw new Exception($"不可更新,未设置主键的值:{_db.Orm.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可更新,未设置主键的值:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
if (_states.TryGetValue(key, out var tryval) == false) if (_states.TryGetValue(key, out var tryval) == false)
{ {
if (isThrow) throw new Exception($"不可更新,数据未被跟踪,应该先查询 或者 Attach{_db.Orm.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可更新,数据未被跟踪,应该先查询 或者 Attach{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
return true; return true;
@ -351,13 +351,13 @@ namespace FreeSql
} }
if (_table.Primarys.Any() == false) if (_table.Primarys.Any() == false)
{ {
if (isThrow) throw new Exception($"不可删除,实体没有主键:{_db.Orm.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可删除,实体没有主键:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
var key = _db.Orm.GetEntityKeyString(_entityType, data, false); var key = _db.OrmOriginal.GetEntityKeyString(_entityType, data, false);
if (string.IsNullOrEmpty(key)) if (string.IsNullOrEmpty(key))
{ {
if (isThrow) throw new Exception($"不可删除,未设置主键的值:{_db.Orm.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可删除,未设置主键的值:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
//if (_states.TryGetValue(key, out var tryval) == false) { //if (_states.TryGetValue(key, out var tryval) == false) {

View File

@ -35,7 +35,7 @@ namespace FreeSql
if (_tableIdentitys.Length > 0) if (_tableIdentitys.Length > 0)
{ {
//有自增,马上执行 //有自增,马上执行
switch (_db.Orm.Ado.DataType) switch (_db.OrmOriginal.Ado.DataType)
{ {
case DataType.SqlServer: case DataType.SqlServer:
case DataType.OdbcSqlServer: case DataType.OdbcSqlServer:
@ -46,7 +46,7 @@ namespace FreeSql
await DbContextExecCommandAsync(); await DbContextExecCommandAsync();
var idtval = await this.OrmInsert(data).ExecuteIdentityAsync(); var idtval = await this.OrmInsert(data).ExecuteIdentityAsync();
IncrAffrows(1); IncrAffrows(1);
_db.Orm.SetEntityIdentityValueWithPrimary(_entityType, data, idtval); _db.OrmOriginal.SetEntityIdentityValueWithPrimary(_entityType, data, idtval);
_db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert }); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert });
Attach(data); Attach(data);
if (_db.Options.EnableAddOrUpdateNavigateList) if (_db.Options.EnableAddOrUpdateNavigateList)
@ -58,7 +58,7 @@ namespace FreeSql
var newval = (await this.OrmInsert(data).ExecuteInsertedAsync()).First(); var newval = (await this.OrmInsert(data).ExecuteInsertedAsync()).First();
_db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = newval, Type = DbContext.EntityChangeType.Insert }); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = newval, Type = DbContext.EntityChangeType.Insert });
IncrAffrows(1); IncrAffrows(1);
_db.Orm.MapEntityValue(_entityType, newval, data); _db.OrmOriginal.MapEntityValue(_entityType, newval, data);
Attach(newval); Attach(newval);
if (_db.Options.EnableAddOrUpdateNavigateList) if (_db.Options.EnableAddOrUpdateNavigateList)
await AddOrUpdateNavigateListAsync(data, true); await AddOrUpdateNavigateListAsync(data, true);
@ -70,7 +70,7 @@ namespace FreeSql
await DbContextExecCommandAsync(); await DbContextExecCommandAsync();
var idtval = await this.OrmInsert(data).ExecuteIdentityAsync(); var idtval = await this.OrmInsert(data).ExecuteIdentityAsync();
IncrAffrows(1); IncrAffrows(1);
_db.Orm.SetEntityIdentityValueWithPrimary(_entityType, data, idtval); _db.OrmOriginal.SetEntityIdentityValueWithPrimary(_entityType, data, idtval);
_db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert }); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert });
Attach(data); Attach(data);
if (_db.Options.EnableAddOrUpdateNavigateList) if (_db.Options.EnableAddOrUpdateNavigateList)
@ -96,7 +96,7 @@ namespace FreeSql
if (_tableIdentitys.Length > 0) if (_tableIdentitys.Length > 0)
{ {
//有自增,马上执行 //有自增,马上执行
switch (_db.Orm.Ado.DataType) switch (_db.OrmOriginal.Ado.DataType)
{ {
case DataType.SqlServer: case DataType.SqlServer:
case DataType.OdbcSqlServer: case DataType.OdbcSqlServer:
@ -104,11 +104,11 @@ namespace FreeSql
case DataType.OdbcPostgreSQL: case DataType.OdbcPostgreSQL:
await DbContextExecCommandAsync(); await DbContextExecCommandAsync();
var rets = await this.OrmInsert(data).ExecuteInsertedAsync(); var rets = await this.OrmInsert(data).ExecuteInsertedAsync();
if (rets.Count != data.Count()) throw new Exception($"特别错误:批量添加失败,{_db.Orm.Ado.DataType} 的返回数据,与添加的数目不匹配"); if (rets.Count != data.Count()) throw new Exception($"特别错误:批量添加失败,{_db.OrmOriginal.Ado.DataType} 的返回数据,与添加的数目不匹配");
_db._entityChangeReport.AddRange(rets.Select(a => new DbContext.EntityChangeReport.ChangeInfo { Object = a, Type = DbContext.EntityChangeType.Insert })); _db._entityChangeReport.AddRange(rets.Select(a => new DbContext.EntityChangeReport.ChangeInfo { Object = a, Type = DbContext.EntityChangeType.Insert }));
var idx = 0; var idx = 0;
foreach (var s in data) foreach (var s in data)
_db.Orm.MapEntityValue(_entityType, rets[idx++], s); _db.OrmOriginal.MapEntityValue(_entityType, rets[idx++], s);
IncrAffrows(rets.Count); IncrAffrows(rets.Count);
AttachRange(rets); AttachRange(rets);
if (_db.Options.EnableAddOrUpdateNavigateList) if (_db.Options.EnableAddOrUpdateNavigateList)
@ -168,13 +168,13 @@ namespace FreeSql
Expression.Constant( Expression.Constant(
FreeSql.Internal.Utils.GetDataReaderValue( FreeSql.Internal.Utils.GetDataReaderValue(
tref.Columns[colidx].CsType, tref.Columns[colidx].CsType,
_db.Orm.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.RefColumns[colidx].CsType) _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.RefColumns[colidx].CsType)
); );
if (whereParentExp == null) whereParentExp = whereExp; if (whereParentExp == null) whereParentExp = whereExp;
else whereParentExp = Expression.AndAlso(whereParentExp, whereExp); else whereParentExp = Expression.AndAlso(whereParentExp, whereExp);
} }
var propValEach = GetItemValue(item, prop) as IEnumerable; var propValEach = GetItemValue(item, prop) as IEnumerable;
var subDelete = _db.Orm.Delete<object>().AsType(tref.RefEntityType) var subDelete = _db.OrmOriginal.Delete<object>().AsType(tref.RefEntityType)
.WithTransaction(_uow?.GetOrBeginTransaction()) .WithTransaction(_uow?.GetOrBeginTransaction())
.Where(Expression.Lambda<Func<object, bool>>(whereParentExp, deleteWhereParentParam)); .Where(Expression.Lambda<Func<object, bool>>(whereParentExp, deleteWhereParentParam));
foreach (var propValItem in propValEach) foreach (var propValItem in propValEach)
@ -230,12 +230,12 @@ namespace FreeSql
Expression.Constant( Expression.Constant(
FreeSql.Internal.Utils.GetDataReaderValue( FreeSql.Internal.Utils.GetDataReaderValue(
tref.MiddleColumns[colidx].CsType, tref.MiddleColumns[colidx].CsType,
_db.Orm.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.MiddleColumns[colidx].CsType) _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.MiddleColumns[colidx].CsType)
), midSelectParam)); ), midSelectParam));
if (curList.Any() == false) //全部删除 if (curList.Any() == false) //全部删除
{ {
var delall = _db.Orm.Delete<object>().AsType(tref.RefMiddleEntityType) var delall = _db.OrmOriginal.Delete<object>().AsType(tref.RefMiddleEntityType)
.WithTransaction(_uow?.GetOrBeginTransaction()); .WithTransaction(_uow?.GetOrBeginTransaction());
foreach (var midWhere in midWheres) delall.Where(midWhere); foreach (var midWhere in midWheres) delall.Where(midWhere);
var sql = delall.ToSql(); var sql = delall.ToSql();
@ -266,8 +266,8 @@ namespace FreeSql
for (var midcolidx = tref.Columns.Count; midcolidx < tref.MiddleColumns.Count; midcolidx++) for (var midcolidx = tref.Columns.Count; midcolidx < tref.MiddleColumns.Count; midcolidx++)
{ {
var refcol = tref.Columns[midcolidx - tref.Columns.Count]; var refcol = tref.Columns[midcolidx - tref.Columns.Count];
var midval = FreeSql.Internal.Utils.GetDataReaderValue(refcol.CsType, _db.Orm.GetEntityValueWithPropertyName(tref.RefMiddleEntityType, midItem, tref.MiddleColumns[midcolidx].CsName)); var midval = FreeSql.Internal.Utils.GetDataReaderValue(refcol.CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(tref.RefMiddleEntityType, midItem, tref.MiddleColumns[midcolidx].CsName));
var refval = FreeSql.Internal.Utils.GetDataReaderValue(refcol.CsType, _db.Orm.GetEntityValueWithPropertyName(tref.RefEntityType, curList[curIdx], tref.Columns[midcolidx - tref.Columns.Count].CsName)); var refval = FreeSql.Internal.Utils.GetDataReaderValue(refcol.CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(tref.RefEntityType, curList[curIdx], tref.Columns[midcolidx - tref.Columns.Count].CsName));
if (object.Equals(midval, refval) == false) if (object.Equals(midval, refval) == false)
{ {
isEquals = false; isEquals = false;
@ -289,14 +289,14 @@ namespace FreeSql
var newItem = Activator.CreateInstance(tref.RefMiddleEntityType); var newItem = Activator.CreateInstance(tref.RefMiddleEntityType);
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.Orm.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));
_db.Orm.SetEntityValueWithPropertyName(tref.RefMiddleEntityType, newItem, tref.MiddleColumns[colidx].CsName, val); _db.OrmOriginal.SetEntityValueWithPropertyName(tref.RefMiddleEntityType, newItem, tref.MiddleColumns[colidx].CsName, val);
} }
for (var midcolidx = tref.Columns.Count; midcolidx < tref.MiddleColumns.Count; midcolidx++) for (var midcolidx = tref.Columns.Count; midcolidx < tref.MiddleColumns.Count; midcolidx++)
{ {
var refcol = tref.RefColumns[midcolidx - tref.Columns.Count]; var refcol = tref.RefColumns[midcolidx - tref.Columns.Count];
var refval = FreeSql.Internal.Utils.GetDataReaderValue(tref.MiddleColumns[midcolidx].CsType, _db.Orm.GetEntityValueWithPropertyName(tref.RefEntityType, curItem, refcol.CsName)); var refval = FreeSql.Internal.Utils.GetDataReaderValue(tref.MiddleColumns[midcolidx].CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(tref.RefEntityType, curItem, refcol.CsName));
_db.Orm.SetEntityValueWithPropertyName(tref.RefMiddleEntityType, newItem, tref.MiddleColumns[midcolidx].CsName, refval); _db.OrmOriginal.SetEntityValueWithPropertyName(tref.RefMiddleEntityType, newItem, tref.MiddleColumns[midcolidx].CsName, refval);
} }
midListAdd.Add(newItem); midListAdd.Add(newItem);
} }
@ -308,8 +308,8 @@ namespace FreeSql
{ {
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.RefColumns[colidx].CsType, _db.Orm.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)); var val = FreeSql.Internal.Utils.GetDataReaderValue(tref.RefColumns[colidx].CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName));
_db.Orm.SetEntityValueWithPropertyName(tref.RefEntityType, propValItem, tref.RefColumns[colidx].CsName, val); _db.OrmOriginal.SetEntityValueWithPropertyName(tref.RefEntityType, propValItem, tref.RefColumns[colidx].CsName, val);
} }
await refSet.AddOrUpdateAsync(propValItem); await refSet.AddOrUpdateAsync(propValItem);
} }
@ -336,10 +336,10 @@ namespace FreeSql
if (_states.TryGetValue(uplst1.Key, out var lstval1) == false) return -999; if (_states.TryGetValue(uplst1.Key, out var lstval1) == false) return -999;
var lstval2 = default(EntityState); var lstval2 = default(EntityState);
if (uplst2 != null && _states.TryGetValue(uplst2.Key, out lstval2) == false) throw new Exception($"特别错误:更新失败,数据未被跟踪:{_db.Orm.GetEntityString(_entityType, uplst2.Value)}"); if (uplst2 != null && _states.TryGetValue(uplst2.Key, out lstval2) == false) throw new Exception($"特别错误:更新失败,数据未被跟踪:{_db.OrmOriginal.GetEntityString(_entityType, uplst2.Value)}");
var cuig1 = _db.Orm.CompareEntityValueReturnColumns(_entityType, uplst1.Value, lstval1.Value, true); var cuig1 = _db.OrmOriginal.CompareEntityValueReturnColumns(_entityType, uplst1.Value, lstval1.Value, true);
var cuig2 = uplst2 != null ? _db.Orm.CompareEntityValueReturnColumns(_entityType, uplst2.Value, lstval2.Value, true) : null; var cuig2 = uplst2 != null ? _db.OrmOriginal.CompareEntityValueReturnColumns(_entityType, uplst2.Value, lstval2.Value, true) : null;
List<EntityState> data = null; List<EntityState> data = null;
string[] cuig = null; string[] cuig = null;
@ -372,9 +372,9 @@ namespace FreeSql
foreach (var newval in data) foreach (var newval in data)
{ {
if (_states.TryGetValue(newval.Key, out var tryold)) if (_states.TryGetValue(newval.Key, out var tryold))
_db.Orm.MapEntityValue(_entityType, newval.Value, tryold.Value); _db.OrmOriginal.MapEntityValue(_entityType, newval.Value, tryold.Value);
if (newval.OldValue != null) if (newval.OldValue != null)
_db.Orm.MapEntityValue(_entityType, newval.Value, newval.OldValue); _db.OrmOriginal.MapEntityValue(_entityType, newval.Value, newval.OldValue);
} }
return affrows; return affrows;
} }
@ -385,11 +385,11 @@ namespace FreeSql
async public Task UpdateAsync(TEntity data) async public Task UpdateAsync(TEntity data)
{ {
var exists = ExistsInStates(data); var exists = ExistsInStates(data);
if (exists == null) throw new Exception($"不可更新,未设置主键的值:{_db.Orm.GetEntityString(_entityType, data)}"); if (exists == null) throw new Exception($"不可更新,未设置主键的值:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
if (exists == false) if (exists == false)
{ {
var olddata = await OrmSelect(data).FirstAsync(); var olddata = await OrmSelect(data).FirstAsync();
if (olddata == null) throw new Exception($"不可更新,数据库不存在该记录:{_db.Orm.GetEntityString(_entityType, data)}"); if (olddata == null) throw new Exception($"不可更新,数据库不存在该记录:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
} }
await UpdateRangePrivAsync(new[] { data }, true); await UpdateRangePrivAsync(new[] { data }, true);
@ -438,7 +438,7 @@ namespace FreeSql
async public Task AddOrUpdateAsync(TEntity data) async public Task AddOrUpdateAsync(TEntity data)
{ {
if (data == null) throw new ArgumentNullException(nameof(data)); if (data == null) throw new ArgumentNullException(nameof(data));
if (_table.Primarys.Any() == false) throw new Exception($"不可添加,实体没有主键:{_db.Orm.GetEntityString(_entityType, data)}"); if (_table.Primarys.Any() == false) throw new Exception($"不可添加,实体没有主键:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
var flagExists = ExistsInStates(data); var flagExists = ExistsInStates(data);
if (flagExists == false) if (flagExists == false)
@ -458,7 +458,7 @@ namespace FreeSql
} }
if (CanAdd(data, false)) if (CanAdd(data, false))
{ {
_db.Orm.ClearEntityPrimaryValueWithIdentity(_entityType, data); _db.OrmOriginal.ClearEntityPrimaryValueWithIdentity(_entityType, data);
await AddPrivAsync(data, false); await AddPrivAsync(data, false);
} }
} }

View File

@ -34,7 +34,7 @@ namespace FreeSql
if (_tableIdentitys.Length > 0) if (_tableIdentitys.Length > 0)
{ {
//有自增,马上执行 //有自增,马上执行
switch (_db.Orm.Ado.DataType) switch (_db.OrmOriginal.Ado.DataType)
{ {
case DataType.SqlServer: case DataType.SqlServer:
case DataType.OdbcSqlServer: case DataType.OdbcSqlServer:
@ -45,7 +45,7 @@ namespace FreeSql
DbContextExecCommand(); DbContextExecCommand();
var idtval = this.OrmInsert(data).ExecuteIdentity(); var idtval = this.OrmInsert(data).ExecuteIdentity();
IncrAffrows(1); IncrAffrows(1);
_db.Orm.SetEntityIdentityValueWithPrimary(_entityType, data, idtval); _db.OrmOriginal.SetEntityIdentityValueWithPrimary(_entityType, data, idtval);
_db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert }); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert });
Attach(data); Attach(data);
if (_db.Options.EnableAddOrUpdateNavigateList) if (_db.Options.EnableAddOrUpdateNavigateList)
@ -57,7 +57,7 @@ namespace FreeSql
var newval = this.OrmInsert(data).ExecuteInserted().First(); var newval = this.OrmInsert(data).ExecuteInserted().First();
_db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = newval, Type = DbContext.EntityChangeType.Insert }); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = newval, Type = DbContext.EntityChangeType.Insert });
IncrAffrows(1); IncrAffrows(1);
_db.Orm.MapEntityValue(_entityType, newval, data); _db.OrmOriginal.MapEntityValue(_entityType, newval, data);
Attach(newval); Attach(newval);
if (_db.Options.EnableAddOrUpdateNavigateList) if (_db.Options.EnableAddOrUpdateNavigateList)
AddOrUpdateNavigateList(data, true); AddOrUpdateNavigateList(data, true);
@ -69,7 +69,7 @@ namespace FreeSql
DbContextExecCommand(); DbContextExecCommand();
var idtval = this.OrmInsert(data).ExecuteIdentity(); var idtval = this.OrmInsert(data).ExecuteIdentity();
IncrAffrows(1); IncrAffrows(1);
_db.Orm.SetEntityIdentityValueWithPrimary(_entityType, data, idtval); _db.OrmOriginal.SetEntityIdentityValueWithPrimary(_entityType, data, idtval);
_db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert }); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert });
Attach(data); Attach(data);
if (_db.Options.EnableAddOrUpdateNavigateList) if (_db.Options.EnableAddOrUpdateNavigateList)
@ -99,7 +99,7 @@ namespace FreeSql
if (_tableIdentitys.Length > 0) if (_tableIdentitys.Length > 0)
{ {
//有自增,马上执行 //有自增,马上执行
switch (_db.Orm.Ado.DataType) switch (_db.OrmOriginal.Ado.DataType)
{ {
case DataType.SqlServer: case DataType.SqlServer:
case DataType.OdbcSqlServer: case DataType.OdbcSqlServer:
@ -107,11 +107,11 @@ namespace FreeSql
case DataType.OdbcPostgreSQL: case DataType.OdbcPostgreSQL:
DbContextExecCommand(); DbContextExecCommand();
var rets = this.OrmInsert(data).ExecuteInserted(); var rets = this.OrmInsert(data).ExecuteInserted();
if (rets.Count != data.Count()) throw new Exception($"特别错误:批量添加失败,{_db.Orm.Ado.DataType} 的返回数据,与添加的数目不匹配"); if (rets.Count != data.Count()) throw new Exception($"特别错误:批量添加失败,{_db.OrmOriginal.Ado.DataType} 的返回数据,与添加的数目不匹配");
_db._entityChangeReport.AddRange(rets.Select(a => new DbContext.EntityChangeReport.ChangeInfo { Object = a, Type = DbContext.EntityChangeType.Insert })); _db._entityChangeReport.AddRange(rets.Select(a => new DbContext.EntityChangeReport.ChangeInfo { Object = a, Type = DbContext.EntityChangeType.Insert }));
var idx = 0; var idx = 0;
foreach (var s in data) foreach (var s in data)
_db.Orm.MapEntityValue(_entityType, rets[idx++], s); _db.OrmOriginal.MapEntityValue(_entityType, rets[idx++], s);
IncrAffrows(rets.Count); IncrAffrows(rets.Count);
AttachRange(rets); AttachRange(rets);
if (_db.Options.EnableAddOrUpdateNavigateList) if (_db.Options.EnableAddOrUpdateNavigateList)
@ -180,13 +180,13 @@ namespace FreeSql
Expression.Constant( Expression.Constant(
FreeSql.Internal.Utils.GetDataReaderValue( FreeSql.Internal.Utils.GetDataReaderValue(
tref.Columns[colidx].CsType, tref.Columns[colidx].CsType,
_db.Orm.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.RefColumns[colidx].CsType) _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.RefColumns[colidx].CsType)
); );
if (whereParentExp == null) whereParentExp = whereExp; if (whereParentExp == null) whereParentExp = whereExp;
else whereParentExp = Expression.AndAlso(whereParentExp, whereExp); else whereParentExp = Expression.AndAlso(whereParentExp, whereExp);
} }
var propValEach = GetItemValue(item, prop) as IEnumerable; var propValEach = GetItemValue(item, prop) as IEnumerable;
var subDelete = _db.Orm.Delete<object>().AsType(tref.RefEntityType) var subDelete = _db.OrmOriginal.Delete<object>().AsType(tref.RefEntityType)
.WithTransaction(_uow?.GetOrBeginTransaction()) .WithTransaction(_uow?.GetOrBeginTransaction())
.Where(Expression.Lambda<Func<object, bool>>(whereParentExp, deleteWhereParentParam)); .Where(Expression.Lambda<Func<object, bool>>(whereParentExp, deleteWhereParentParam));
foreach (var propValItem in propValEach) foreach (var propValItem in propValEach)
@ -242,12 +242,12 @@ namespace FreeSql
Expression.Constant( Expression.Constant(
FreeSql.Internal.Utils.GetDataReaderValue( FreeSql.Internal.Utils.GetDataReaderValue(
tref.MiddleColumns[colidx].CsType, tref.MiddleColumns[colidx].CsType,
_db.Orm.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.MiddleColumns[colidx].CsType) _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.MiddleColumns[colidx].CsType)
), midSelectParam)); ), midSelectParam));
if (curList.Any() == false) //全部删除 if (curList.Any() == false) //全部删除
{ {
var delall = _db.Orm.Delete<object>().AsType(tref.RefMiddleEntityType) var delall = _db.OrmOriginal.Delete<object>().AsType(tref.RefMiddleEntityType)
.WithTransaction(_uow?.GetOrBeginTransaction()); .WithTransaction(_uow?.GetOrBeginTransaction());
foreach (var midWhere in midWheres) delall.Where(midWhere); foreach (var midWhere in midWheres) delall.Where(midWhere);
var sql = delall.ToSql(); var sql = delall.ToSql();
@ -278,8 +278,8 @@ namespace FreeSql
for (var midcolidx = tref.Columns.Count; midcolidx < tref.MiddleColumns.Count; midcolidx++) for (var midcolidx = tref.Columns.Count; midcolidx < tref.MiddleColumns.Count; midcolidx++)
{ {
var refcol = tref.RefColumns[midcolidx - tref.Columns.Count]; var refcol = tref.RefColumns[midcolidx - tref.Columns.Count];
var midval = FreeSql.Internal.Utils.GetDataReaderValue(refcol.CsType, _db.Orm.GetEntityValueWithPropertyName(tref.RefMiddleEntityType, midItem, tref.MiddleColumns[midcolidx].CsName)); var midval = FreeSql.Internal.Utils.GetDataReaderValue(refcol.CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(tref.RefMiddleEntityType, midItem, tref.MiddleColumns[midcolidx].CsName));
var refval = FreeSql.Internal.Utils.GetDataReaderValue(refcol.CsType, _db.Orm.GetEntityValueWithPropertyName(tref.RefEntityType, curList[curIdx], refcol.CsName)); var refval = FreeSql.Internal.Utils.GetDataReaderValue(refcol.CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(tref.RefEntityType, curList[curIdx], refcol.CsName));
if (object.Equals(midval, refval) == false) if (object.Equals(midval, refval) == false)
{ {
isEquals = false; isEquals = false;
@ -301,14 +301,14 @@ namespace FreeSql
var newItem = Activator.CreateInstance(tref.RefMiddleEntityType); var newItem = Activator.CreateInstance(tref.RefMiddleEntityType);
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.Orm.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));
_db.Orm.SetEntityValueWithPropertyName(tref.RefMiddleEntityType, newItem, tref.MiddleColumns[colidx].CsName, val); _db.OrmOriginal.SetEntityValueWithPropertyName(tref.RefMiddleEntityType, newItem, tref.MiddleColumns[colidx].CsName, val);
} }
for (var midcolidx = tref.Columns.Count; midcolidx < tref.MiddleColumns.Count; midcolidx++) for (var midcolidx = tref.Columns.Count; midcolidx < tref.MiddleColumns.Count; midcolidx++)
{ {
var refcol = tref.RefColumns[midcolidx - tref.Columns.Count]; var refcol = tref.RefColumns[midcolidx - tref.Columns.Count];
var refval = FreeSql.Internal.Utils.GetDataReaderValue(tref.MiddleColumns[midcolidx].CsType, _db.Orm.GetEntityValueWithPropertyName(tref.RefEntityType, curItem, refcol.CsName)); var refval = FreeSql.Internal.Utils.GetDataReaderValue(tref.MiddleColumns[midcolidx].CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(tref.RefEntityType, curItem, refcol.CsName));
_db.Orm.SetEntityValueWithPropertyName(tref.RefMiddleEntityType, newItem, tref.MiddleColumns[midcolidx].CsName, refval); _db.OrmOriginal.SetEntityValueWithPropertyName(tref.RefMiddleEntityType, newItem, tref.MiddleColumns[midcolidx].CsName, refval);
} }
midListAdd.Add(newItem); midListAdd.Add(newItem);
} }
@ -320,8 +320,8 @@ namespace FreeSql
{ {
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.RefColumns[colidx].CsType, _db.Orm.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)); var val = FreeSql.Internal.Utils.GetDataReaderValue(tref.RefColumns[colidx].CsType, _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName));
_db.Orm.SetEntityValueWithPropertyName(tref.RefEntityType, propValItem, tref.RefColumns[colidx].CsName, val); _db.OrmOriginal.SetEntityValueWithPropertyName(tref.RefEntityType, propValItem, tref.RefColumns[colidx].CsName, val);
} }
refSet.AddOrUpdate(propValItem); refSet.AddOrUpdate(propValItem);
} }
@ -371,10 +371,10 @@ namespace FreeSql
if (_states.TryGetValue(uplst1.Key, out var lstval1) == false) return -999; if (_states.TryGetValue(uplst1.Key, out var lstval1) == false) return -999;
var lstval2 = default(EntityState); var lstval2 = default(EntityState);
if (uplst2 != null && _states.TryGetValue(uplst2.Key, out lstval2) == false) throw new Exception($"特别错误:更新失败,数据未被跟踪:{_db.Orm.GetEntityString(_entityType, uplst2.Value)}"); if (uplst2 != null && _states.TryGetValue(uplst2.Key, out lstval2) == false) throw new Exception($"特别错误:更新失败,数据未被跟踪:{_db.OrmOriginal.GetEntityString(_entityType, uplst2.Value)}");
var cuig1 = _db.Orm.CompareEntityValueReturnColumns(_entityType, uplst1.Value, lstval1.Value, true); var cuig1 = _db.OrmOriginal.CompareEntityValueReturnColumns(_entityType, uplst1.Value, lstval1.Value, true);
var cuig2 = uplst2 != null ? _db.Orm.CompareEntityValueReturnColumns(_entityType, uplst2.Value, lstval2.Value, true) : null; var cuig2 = uplst2 != null ? _db.OrmOriginal.CompareEntityValueReturnColumns(_entityType, uplst2.Value, lstval2.Value, true) : null;
List<EntityState> data = null; List<EntityState> data = null;
string[] cuig = null; string[] cuig = null;
@ -407,9 +407,9 @@ namespace FreeSql
foreach (var newval in data) foreach (var newval in data)
{ {
if (_states.TryGetValue(newval.Key, out var tryold)) if (_states.TryGetValue(newval.Key, out var tryold))
_db.Orm.MapEntityValue(_entityType, newval.Value, tryold.Value); _db.OrmOriginal.MapEntityValue(_entityType, newval.Value, tryold.Value);
if (newval.OldValue != null) if (newval.OldValue != null)
_db.Orm.MapEntityValue(_entityType, newval.Value, newval.OldValue); _db.OrmOriginal.MapEntityValue(_entityType, newval.Value, newval.OldValue);
} }
return affrows; return affrows;
} }
@ -426,11 +426,11 @@ namespace FreeSql
public void Update(TEntity data) public void Update(TEntity data)
{ {
var exists = ExistsInStates(data); var exists = ExistsInStates(data);
if (exists == null) throw new Exception($"不可更新,未设置主键的值:{_db.Orm.GetEntityString(_entityType, data)}"); if (exists == null) throw new Exception($"不可更新,未设置主键的值:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
if (exists == false) if (exists == false)
{ {
var olddata = OrmSelect(data).First(); var olddata = OrmSelect(data).First();
if (olddata == null) throw new Exception($"不可更新,数据库不存在该记录:{_db.Orm.GetEntityString(_entityType, data)}"); if (olddata == null) throw new Exception($"不可更新,数据库不存在该记录:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
} }
UpdateRangePriv(new[] { data }, true); UpdateRangePriv(new[] { data }, true);
@ -476,7 +476,7 @@ namespace FreeSql
{ {
var state = CreateEntityState(item); var state = CreateEntityState(item);
_states.TryRemove(state.Key, out var trystate); _states.TryRemove(state.Key, out var trystate);
_db.Orm.ClearEntityPrimaryValueWithIdentityAndGuid(_entityType, item); _db.OrmOriginal.ClearEntityPrimaryValueWithIdentityAndGuid(_entityType, item);
EnqueueToDbContext(DbContext.EntityChangeType.Delete, state); EnqueueToDbContext(DbContext.EntityChangeType.Delete, state);
} }
@ -501,7 +501,7 @@ namespace FreeSql
public void AddOrUpdate(TEntity data) public void AddOrUpdate(TEntity data)
{ {
if (data == null) throw new ArgumentNullException(nameof(data)); if (data == null) throw new ArgumentNullException(nameof(data));
if (_table.Primarys.Any() == false) throw new Exception($"不可添加,实体没有主键:{_db.Orm.GetEntityString(_entityType, data)}"); if (_table.Primarys.Any() == false) throw new Exception($"不可添加,实体没有主键:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
var flagExists = ExistsInStates(data); var flagExists = ExistsInStates(data);
if (flagExists == false) if (flagExists == false)
@ -521,7 +521,7 @@ namespace FreeSql
} }
if (CanAdd(data, false)) if (CanAdd(data, false))
{ {
_db.Orm.ClearEntityPrimaryValueWithIdentity(_entityType, data); _db.OrmOriginal.ClearEntityPrimaryValueWithIdentity(_entityType, data);
AddPriv(data, false); AddPriv(data, false);
} }
} }

View File

@ -23,14 +23,14 @@ namespace FreeSql
{ {
throw new Exception($"AddFreeDbContext 发生错误,请检查 {dbContextType.Name} 的构造参数都已正确注入", ex); throw new Exception($"AddFreeDbContext 发生错误,请检查 {dbContextType.Name} 的构造参数都已正确注入", ex);
} }
if (ctx != null && ctx._ormPriv == null) if (ctx != null && ctx._ormScoped == null)
{ {
var builder = new DbContextOptionsBuilder(); var builder = new DbContextOptionsBuilder();
options(builder); options(builder);
ctx._ormPriv = builder._fsql; ctx._ormScoped = DbContextScopedFreeSql.Create(builder._fsql, () => ctx, () => ctx.UnitOfWork);
ctx._optionsPriv = builder._options; ctx._optionsPriv = builder._options;
if (ctx._ormPriv == null) if (ctx._ormScoped == null)
throw new Exception("请在 OnConfiguring 或 AddFreeDbContext 中配置 UseFreeSql"); throw new Exception("请在 OnConfiguring 或 AddFreeDbContext 中配置 UseFreeSql");
ctx.InitPropSets(); ctx.InitPropSets();

View File

@ -4,12 +4,6 @@
<name>FreeSql.DbContext</name> <name>FreeSql.DbContext</name>
</assembly> </assembly>
<members> <members>
<member name="P:FreeSql.DbContext.Orm">
<summary>
注意IFreeSql 属于顶级对象,事务无法自动传递。<para></para>
手工传递事务ISelect/IInsert/IDelete/IUpdate 可以使用 WithTransaction(uow.GetOrBeginTransaction())
</summary>
</member>
<member name="M:FreeSql.DbContext.Add``1(``0)"> <member name="M:FreeSql.DbContext.Add``1(``0)">
<summary> <summary>
添加 添加
@ -231,12 +225,6 @@
<param name="assemblies"></param> <param name="assemblies"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="P:FreeSql.IBaseRepository.Orm">
<summary>
注意IFreeSql 属于顶级对象,事务无法自动传递。<para></para>
手工传递事务ISelect/IInsert/IDelete/IUpdate 可以使用 WithTransaction(uow.GetOrBeginTransaction())
</summary>
</member>
<member name="M:FreeSql.IBaseRepository.AsType(System.Type)"> <member name="M:FreeSql.IBaseRepository.AsType(System.Type)">
<summary> <summary>
动态Type在使用 Repository&lt;object&gt; 后使用本方法,指定实体类型 动态Type在使用 Repository&lt;object&gt; 后使用本方法,指定实体类型

View File

@ -11,7 +11,7 @@ namespace FreeSql
protected IBaseRepository _repo; protected IBaseRepository _repo;
public RepositoryDbContext(IFreeSql orm, IBaseRepository repo) : base() public RepositoryDbContext(IFreeSql orm, IBaseRepository repo) : base()
{ {
_ormPriv = orm; _ormScoped = DbContextScopedFreeSql.Create(orm, () => this, () => repo.UnitOfWork);
_isUseUnitOfWork = false; _isUseUnitOfWork = false;
UnitOfWork = repo.UnitOfWork; UnitOfWork = repo.UnitOfWork;
_repo = repo; _repo = repo;
@ -23,7 +23,7 @@ namespace FreeSql
{ {
if (_dicSet.ContainsKey(entityType)) return _dicSet[entityType]; if (_dicSet.ContainsKey(entityType)) return _dicSet[entityType];
var tb = _ormPriv.CodeFirst.GetTableByEntity(entityType); var tb = OrmOriginal.CodeFirst.GetTableByEntity(entityType);
if (tb == null) return null; if (tb == null) return null;
object repo = _repo; object repo = _repo;

View File

@ -34,7 +34,7 @@ namespace FreeSql
if (entitys != null) if (entitys != null)
foreach (var entity in entitys) foreach (var entity in entitys)
if (filter.Value.ExpressionDelegate?.Invoke(entity) == false) if (filter.Value.ExpressionDelegate?.Invoke(entity) == false)
throw new Exception($"FreeSql.Repository Update 失败,因为设置了过滤器 {filter.Key}: {filter.Value.Expression},更新的数据不符合 {_db.Orm.GetEntityString(_entityType, entity)}"); throw new Exception($"FreeSql.Repository Update 失败,因为设置了过滤器 {filter.Key}: {filter.Value.Expression},更新的数据不符合 {_db.OrmOriginal.GetEntityString(_entityType, entity)}");
update.Where(filter.Value.Expression); update.Where(filter.Value.Expression);
} }
return update.AsTable(_repo.AsTableValueInternal); return update.AsTable(_repo.AsTableValueInternal);
@ -58,7 +58,7 @@ namespace FreeSql
if (entitys != null) if (entitys != null)
foreach (var entity in entitys) foreach (var entity in entitys)
if (filter.Value.ExpressionDelegate?.Invoke(entity) == false) if (filter.Value.ExpressionDelegate?.Invoke(entity) == false)
throw new Exception($"FreeSql.Repository Insert 失败,因为设置了过滤器 {filter.Key}: {filter.Value.Expression},插入的数据不符合 {_db.Orm.GetEntityString(_entityType, entity)}"); throw new Exception($"FreeSql.Repository Insert 失败,因为设置了过滤器 {filter.Key}: {filter.Value.Expression},插入的数据不符合 {_db.OrmOriginal.GetEntityString(_entityType, entity)}");
} }
return insert.AsTable(_repo.AsTableValueInternal); return insert.AsTable(_repo.AsTableValueInternal);
} }

View File

@ -13,7 +13,7 @@ namespace FreeSql
{ {
internal RepositoryDbContext _dbPriv; //这个不能私有化,有地方需要反射获取它 internal RepositoryDbContext _dbPriv; //这个不能私有化,有地方需要反射获取它
internal RepositoryDbContext _db => _dbPriv ?? (_dbPriv = new RepositoryDbContext(Orm, this)); internal RepositoryDbContext _db => _dbPriv ?? (_dbPriv = new RepositoryDbContext(OrmOriginal, this));
internal RepositoryDbSet<TEntity> _dbsetPriv; internal RepositoryDbSet<TEntity> _dbsetPriv;
internal RepositoryDbSet<TEntity> _dbset => _dbsetPriv ?? (_dbsetPriv = _db.Set<TEntity>() as RepositoryDbSet<TEntity>); internal RepositoryDbSet<TEntity> _dbset => _dbsetPriv ?? (_dbsetPriv = _db.Set<TEntity>() as RepositoryDbSet<TEntity>);
@ -25,7 +25,7 @@ namespace FreeSql
protected BaseRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable = null) protected BaseRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable = null)
{ {
Orm = fsql; _ormScoped = DbContextScopedFreeSql.Create(fsql, () => _db, () => UnitOfWork);
DataFilterUtil.SetRepositoryDataFilter(this, null); DataFilterUtil.SetRepositoryDataFilter(this, null);
DataFilter.Apply("", filter); DataFilter.Apply("", filter);
AsTable(asTable); AsTable(asTable);
@ -56,7 +56,9 @@ namespace FreeSql
} }
public DbContextOptions DbContextOptions { get => _db.Options; set => _db.Options = value; } public DbContextOptions DbContextOptions { get => _db.Options; set => _db.Options = value; }
public IFreeSql Orm { get; private set; } internal DbContextScopedFreeSql _ormScoped;
internal IFreeSql OrmOriginal => _ormScoped?._originalFsql;
public IFreeSql Orm => _ormScoped;
IUnitOfWork _unitOfWork; IUnitOfWork _unitOfWork;
public IUnitOfWork UnitOfWork public IUnitOfWork UnitOfWork
{ {
@ -64,6 +66,7 @@ namespace FreeSql
{ {
_unitOfWork = value; _unitOfWork = value;
if (_dbsetPriv != null) _dbsetPriv._uow = _unitOfWork; //防止 dbset 对象已经存在,再次设置 UnitOfWork 无法生效,所以作此判断重新设置 if (_dbsetPriv != null) _dbsetPriv._uow = _unitOfWork; //防止 dbset 对象已经存在,再次设置 UnitOfWork 无法生效,所以作此判断重新设置
if (_dbPriv != null) _dbPriv.UnitOfWork = _unitOfWork;
} }
get => _unitOfWork; get => _unitOfWork;
} }
@ -147,11 +150,11 @@ namespace FreeSql
TEntity CheckTKeyAndReturnIdEntity(TKey id) TEntity CheckTKeyAndReturnIdEntity(TKey id)
{ {
var tb = _db.Orm.CodeFirst.GetTableByEntity(EntityType); var tb = _db.OrmOriginal.CodeFirst.GetTableByEntity(EntityType);
if (tb.Primarys.Length != 1) throw new Exception($"实体类型 {EntityType.Name} 主键数量不为 1无法使用该方法"); if (tb.Primarys.Length != 1) throw new Exception($"实体类型 {EntityType.Name} 主键数量不为 1无法使用该方法");
if (tb.Primarys[0].CsType.NullableTypeOrThis() != typeof(TKey).NullableTypeOrThis()) throw new Exception($"实体类型 {EntityType.Name} 主键类型不为 {typeof(TKey).FullName},无法使用该方法"); if (tb.Primarys[0].CsType.NullableTypeOrThis() != typeof(TKey).NullableTypeOrThis()) throw new Exception($"实体类型 {EntityType.Name} 主键类型不为 {typeof(TKey).FullName},无法使用该方法");
var obj = Activator.CreateInstance(tb.Type); var obj = Activator.CreateInstance(tb.Type);
_db.Orm.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($"实体类型 {EntityType.Name} 无法转换为 {typeof(TEntity).Name},无法使用该方法"); if (ret == null) throw new Exception($"实体类型 {EntityType.Name} 无法转换为 {typeof(TEntity).Name},无法使用该方法");
return ret; return ret;

View File

@ -10,11 +10,6 @@ namespace FreeSql
{ {
Type EntityType { get; } Type EntityType { get; }
IUnitOfWork UnitOfWork { get; set; } IUnitOfWork UnitOfWork { get; set; }
/// <summary>
/// 注意IFreeSql 属于顶级对象,事务无法自动传递。<para></para>
/// 手工传递事务ISelect/IInsert/IDelete/IUpdate 可以使用 WithTransaction(uow.GetOrBeginTransaction())
/// </summary>
IFreeSql Orm { get; } IFreeSql Orm { get; }
/// <summary> /// <summary>

View File

@ -29,6 +29,13 @@ namespace FreeSql.Tests
item = repos.Find(item.Id); item = repos.Find(item.Id);
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(item)); Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(item));
repos.Orm.Insert(new AddUpdateInfo()).ExecuteAffrows();
repos.Orm.Insert(new AddUpdateInfo { Id = Guid.NewGuid() }).ExecuteAffrows();
repos.Orm.Update<AddUpdateInfo>().Set(a => a.Title == "xxx").Where(a => a.Id == item.Id).ExecuteAffrows();
item = repos.Orm.Select<AddUpdateInfo>(item).First();
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(item));
repos.Orm.Delete<AddUpdateInfo>(item).ExecuteAffrows();
} }
[Fact] [Fact]
@ -122,6 +129,7 @@ namespace FreeSql.Tests
{ {
flowRepos = uow.GetRepository<FlowModel>(); flowRepos = uow.GetRepository<FlowModel>();
flowRepos.Insert(flow); flowRepos.Insert(flow);
flowRepos.Orm.Select<FlowModel>().ToList();
uow.Commit(); uow.Commit();
} }
} }
@ -158,6 +166,7 @@ namespace FreeSql.Tests
uow.Close(); uow.Close();
var uowFlowRepos = uow.GetRepository<FlowModel>(); var uowFlowRepos = uow.GetRepository<FlowModel>();
uowFlowRepos.Insert(flow); uowFlowRepos.Insert(flow);
uowFlowRepos.Orm.Select<FlowModel>().ToList();
//已关闭工作单元提不提交都没影响此处注释来确定工作单元开关是否生效关闭了不Commit也应该插入数据 //已关闭工作单元提不提交都没影响此处注释来确定工作单元开关是否生效关闭了不Commit也应该插入数据
//uow.Commit(); //uow.Commit();
} }
@ -199,6 +208,7 @@ namespace FreeSql.Tests
{ {
var uowFlowRepos = uow.GetRepository<FlowModel>(); var uowFlowRepos = uow.GetRepository<FlowModel>();
uowFlowRepos.Insert(flow); uowFlowRepos.Insert(flow);
uowFlowRepos.Orm.Select<FlowModel>().ToList();
//有了任意 Insert/Update/Delete 调用关闭uow的方法将会发生异常 //有了任意 Insert/Update/Delete 调用关闭uow的方法将会发生异常
uow.Close(); uow.Close();
uow.Commit(); uow.Commit();
@ -240,6 +250,7 @@ namespace FreeSql.Tests
{ {
var uowFlowRepos = uow.GetRepository<FlowModel>(); var uowFlowRepos = uow.GetRepository<FlowModel>();
uowFlowRepos.Insert(flow); uowFlowRepos.Insert(flow);
uowFlowRepos.Orm.Select<FlowModel>().ToList();
//不调用commit将不会提交数据库更改 //不调用commit将不会提交数据库更改
//uow.Commit(); //uow.Commit();
} }

View File

@ -118,6 +118,8 @@ namespace FreeSql.Tests
}; };
ctx.AddRange(new[] { song1, song2, song3 }); ctx.AddRange(new[] { song1, song2, song3 });
ctx.Orm.Select<Tag>().Limit(10).ToList();
ctx.AddRange( ctx.AddRange(
new[] { new[] {
new Song_tag { Song_id = song1.Id, Tag_id = tag1.Id }, new Song_tag { Song_id = song1.Id, Tag_id = tag1.Id },
@ -150,7 +152,7 @@ namespace FreeSql.Tests
using (var ctx = g.sqlite.CreateDbContext()) using (var ctx = g.sqlite.CreateDbContext())
{ {
ctx.Options.EnableAddOrUpdateNavigateList = true;
var tags = ctx.Set<Tag>().Select.IncludeMany(a => a.Tags).ToList(); var tags = ctx.Set<Tag>().Select.IncludeMany(a => a.Tags).ToList();
var tag = new Tag var tag = new Tag
@ -168,6 +170,9 @@ namespace FreeSql.Tests
} }
}; };
ctx.Add(tag); ctx.Add(tag);
var tags2 = ctx.Orm.Select<Tag>().IncludeMany(a => a.Tags).ToList();
ctx.SaveChanges(); ctx.SaveChanges();
} }
} }
@ -179,10 +184,12 @@ namespace FreeSql.Tests
using (var ctx = g.sqlite.CreateDbContext()) using (var ctx = g.sqlite.CreateDbContext())
{ {
ctx.Options.EnableAddOrUpdateNavigateList = true;
var tag = ctx.Set<Tag>().Select.First(); var tag = ctx.Set<Tag>().Select.First();
tag.Tags.Add(new Tag { Name = "sub3" }); tag.Tags.Add(new Tag { Name = "sub3" });
tag.Name = Guid.NewGuid().ToString();
ctx.Update(tag); ctx.Update(tag);
var xxx = ctx.Orm.Select<Tag>().First();
ctx.SaveChanges(); ctx.SaveChanges();
} }
} }

View File

@ -2869,203 +2869,32 @@
<summary> <summary>
从对象池获取对象成功的时候触发,通过该方法统计或初始化对象 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
</summary> </summary>
<param na <param name="column"></param> <param name="obj">资源对象</param>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnReturn(FreeSql.Internal.ObjectPool.Object{`0})">
<summary>
归还对象给对象池的时候触发
</summary>
<param name="obj">资源对象</param>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnCheckAvailable(FreeSql.Internal.ObjectPool.Object{`0})">
<summary>
检查可用性
</summary>
<param name="obj">资源对象</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:FreeSql.IDbFirst.GetCsParse(FreeSql.DatabaseModel.DbColumnInfo)"> <member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnAvailable">
<summary> <summary>
反序列化 事件:可用时触发
</summary>
<param name="column"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IDbFirst.GetEnumsByDatabase(System.String[])">
<summary>
获取数据库枚举类型,适用 PostgreSQL
</summary>
<param name="database"></param>
<returns></returns>
</member>
<member name="M:FreeSql.Internal.CommonProvider.InsertProvider`1.IgnoreCanInsert">
<summary>
AsType, Ctor, ClearData 三处地方需要重新加载
</summary> </summary>
</member> </member>
<member name="M:FreeSql.Internal.CommonProvider.UpdateProvider`1.IgnoreCanUpdate"> <member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnUnavailable">
<summary> <summary>
AsType, Ctor, ClearData 三处地方需要重新加载 事件:不可用时触发
</summary> </summary>
</member> </member>
<member name="M:FreeSql.Internal.CommonUtils.GetProperyCommentBySummary(System.Type)"> <member name="P:FreeSql.Internal.ObjectPool.Object`1.Pool">
<summary>
通过属性的注释文本,通过 xml 读取
</summary>
<param name="type"></param>
<returns>Dictkey=属性名value=注释</returns>
</member>
<member name="M:FreeSql.Internal.GlobalFilter.Apply``1(System.String,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<summary>
创建一个过滤器
</summary>
<typeparam name="TEntity"></typeparam>
<param name="name">名字</param>
<param name="where">表达式</param>
<returns></returns>
</member>
<member name="P:FreeSql.Internal.Model.TableRef.RefMiddleEntityType">
<summary>
中间表,多对多
</summary>
</member>
<member name="P:FreeSql.Internal.ObjectPool.IObjectPool`1.IsAvailable">
<summary>
是否可用
</summary>
</member>
<member name="P:FreeSql.Internal.ObjectPool.IObjectPool`1.UnavailableException">
<summary>
不可用错误
</summary>
</member>
<member name="P:FreeSql.Internal.ObjectPool.IObjectPool`1.UnavailableTime">
<summary>
不可用时间
</summary>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.SetUnavailable(System.Exception)">
<summary>
将对象池设置为不可用,后续 Get/GetAsync 均会报错,同时启动后台定时检查服务恢复可用
</summary>
<param name="exception"></param>
<returns>由【可用】变成【不可用】时返回true否则返回false</returns>
</member>
<member name="P:FreeSql.Internal.ObjectPool.IObjectPool`1.Statistics">
<summary>
统计对象池中的对象
</summary>
</member>
<member name="P:FreeSql.Internal.ObjectPool.IObjectPool`1.StatisticsFullily">
<summary>
统计对象池中的对象(完整)
</summary>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.Get(System.Nullable{System.TimeSpan})">
<summary>
获取资源
</summary>
<param name="timeout">超时</param>
<returns></returns>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.GetAsync">
<summary>
获取资源
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.Return(FreeSql.Internal.ObjectPool.Object{`0},System.Boolean)">
<summary>
使用完毕后,归还资源
< </summary>
<returns></returns>
</member>
<member name="F:FreeSql.Internal.StringConvertType.None">
<summary>
不进行任何处理
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.PascalCaseToUnderscore">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串
<para></para>
BigApple -> Big_Apple
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.PascalCaseToUnderscoreWithUpper">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全大写
<para></para>
BigApple -> BIG_APPLE
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.PascalCaseToUnderscoreWithLower">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全小写
<para></para>
BigApple -> big_apple
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.Upper">
<summary>
将字符串转换为大写
<para></para>
BigApple -> BIGAPPLE
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.Lower">
<summary>
将字符串转换为小写
<para></para>
BigApple -> bigapple
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.None">
<summary>
不进行任何处理
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.PascalCaseToUnderscore">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串
<para></para>
BigApple -> Big_Apple
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.PascalCaseToUnderscoreWithUpper">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全大写
<para></para>
BigApple -> BIG_APPLE
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.PascalCaseToUnderscoreWithLower">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全小写
<para></para>
BigApple -> big_apple
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.ToUpper">
<summary>
将字符串转换为大写
<para></para>
BigApple -> BIGAPPLE
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.ToLower">
<summary>
将字符串转换为小写
<para></para>
BigApple -> bigapple
</summary>
</member>
<member name="M:FreeSqlGlobalExpressionCall.Between(System.DateTime,System.DateTime,System.DateTime)">
<summary>
C# that >= between &amp;&amp; that &lt;= and<para></para>
SQL that BETWEEN between AND and
</summary>
<param name="that"></param>
<param name="between"></param>
<param name="and"></param>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalExpressionCall.BetweenEnd(System.DateTime,System.DateTime,System.DateTime)">
<summary>
注意:这个方法和 Between 有细微区别<para></para>
C# that >= start &amp;&amp; that &lt; end<para></para>
SQL that >= start and that &lt; end
</summary>
<param name="that"></param>
<param name="start"></param> Object`1.Pool">
<summary> <summary>
所属对象池 所属对象池
</summary> </summary>
@ -3420,103 +3249,72 @@
将 lambda 表达式取反 将 lambda 表达式取反
</summary> </summary>
<param name="exp"></param> <param name="exp"></param>
<param name=" <summary> <param name="condition">true 时生效</param>
生成类似Mongodb的ObjectId有序、不重复Guid <returns></returns>
</member>
<member name="M:System.Linq.Expressions.LambadaExpressionExtensions.And``3(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,System.Boolean}},System.Linq.Expressions.Expression{System.Func{``0,``1,``2,System.Boolean}})">
<summary>
使用 and 拼接两个 lambda 表达式
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IFreeSql.Insert``1"> <member name="M:System.Linq.Expressions.LambadaExpressionExtensions.And``3(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,System.Boolean}},System.Boolean,System.Linq.Expressions.Expression{System.Func{``0,``1,``2,System.Boolean}})">
<summary> <summary>
插入数据 使用 and 拼接两个 lambda 表达式
</summary> </summary>
<typeparam name="T1"></typeparam> <param name="exp1"></param>
<param name="condition">true 时生效</param>
<param name="exp2"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IFreeSql.Insert``1(``0)"> <member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Or``3(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,System.Boolean}},System.Linq.Expressions.Expression{System.Func{``0,``1,``2,System.Boolean}})">
<summary> <summary>
插入数据,传入实体 使用 or 拼接两个 lambda 表达式
</summary> </summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IFreeSql.Insert``1(``0[])"> <member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Or``3(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,System.Boolean}},System.Boolean,System.Linq.Expressions.Expression{System.Func{``0,``1,``2,System.Boolean}})">
<summary> <summary>
插入数据,传入实体数组 使用 or 拼接两个 lambda 表达式
</summary> </summary>
<typeparam name="T1"></typeparam> <param name="exp1"></param>
<param name="source"></param> <param name="condition">true 时生效</param>
<param name="exp2"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.List{``0})"> <member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Not``3(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,System.Boolean}},System.Boolean)">
<summary> <summary>
插入数据,传入实体集合 将 lambda 表达式取反
</summary> </summary>
<typeparam name="T1"></typeparam> <param name="exp"></param>
<param name="source"></param> <param name="condition">true 时生效</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.IEnumerable{``0})"> <member name="M:System.Linq.Expressions.LambadaExpressionExtensions.And``4(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,System.Boolean}},System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,System.Boolean}})">
<summary> <summary>
插入数据,传入实体集合 使用 and 拼接两个 lambda 表达式
</summary> </summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IFreeSql.Update``1"> <member name="M:System.Linq.Expressions.LambadaExpressionExtensions.And``4(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,System.Boolean}},System.Boolean,System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,System.Boolean}})">
<summary> <summary>
修改数据 使用 and 拼接两个 lambda 表达式
</summary> </summary>
<typeparam name="T1"></typeparam> <param name="exp1"></param>
<param name="condition">true 时生效</param>
<param name="exp2"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IFreeSql.Update``1(System.Object)"> <member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Or``4(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,System.Boolean}},System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,System.Boolean}})">
<summary> <summary>
修改数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} 使用 or 拼接两个 lambda 表达式
</summary> </summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IFreeSql.Select``1"> <member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Or``4(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,System.Boolean}},System.Boolean,System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,System.Boolean}})">
<summary> <summary>
查询数据 使用 or 拼接两个 lambda 表达式
</summary> </summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Select``1(System.Object)">
<summary>
查询数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Delete``1">
<summary>
删除数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Delete``1(System.Object)">
<summary>
删除数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Transaction(System.Action)">
<summary>
开启事务不支持异步60秒未执行完成可能被其他线程事务自动提交
</summary>
<param name="handler">事务体 () => {}</param>
</member>
<member name="M:IFreeSql.Transaction(System.TimeSpan,System.Action)">
<summary>
<param name="exp1"></param> <param name="exp1"></param>
<param name="condition">true 时生效</param> <param name="condition">true 时生效</param>
<param name="exp2"></param> <param name="exp2"></param>
@ -3705,4 +3503,167 @@
</summary> </summary>
</member> </member>
</members> </members>
</doc>
<returns></returns>
</member>
<member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Or``5(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}},System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}})">
<summary>
使用 or 拼接两个 lambda 表达式
</summary>
<returns></returns>
</member>
<member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Or``5(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}},System.Boolean,System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}})">
<summary>
使用 or 拼接两个 lambda 表达式
</summary>
<param name="exp1"></param>
<param name="condition">true 时生效</param>
<param name="exp2"></param>
<returns></returns>
</member>
<member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Not``5(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}},System.Boolean)">
<summary>
将 lambda 表达式取反
</summary>
<param name="exp"></param>
<param name="condition">true 时生效</param>
<returns></returns>
</member>
<member name="M:FreeUtil.NewMongodbId">
<summary>
生成类似Mongodb的ObjectId有序、不重复Guid
</summary>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1">
<summary>
插入数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(``0)">
<summary>
插入数据,传入实体
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(``0[])">
<summary>
插入数据,传入实体数组
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.List{``0})">
<summary>
插入数据,传入实体集合
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.IEnumerable{``0})">
<summary>
插入数据,传入实体集合
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.Update``1">
<summary>
修改数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Update``1(System.Object)">
<summary>
修改数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Select``1">
<summary>
查询数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Select``1(System.Object)">
<summary>
查询数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Delete``1">
<summary>
删除数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Delete``1(System.Object)">
<summary>
删除数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Transaction(System.Action)">
<summary>
开启事务不支持异步60秒未执行完成可能被其他线程事务自动提交
</summary>
<param name="handler">事务体 () => {}</param>
</member>
<member name="M:IFreeSql.Transaction(System.TimeSpan,System.Action)">
<summary>
开启事务(不支持异步)
</summary>
<param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
<param name="handler">事务体 () => {}</param>
</member>
<member name="M:IFreeSql.Transaction(System.Data.IsolationLevel,System.TimeSpan,System.Action)">
<summary>
开启事务(不支持异步)
</summary>
<param name="isolationLevel"></param>
<param name="handler">事务体 () => {}</param>
<param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
</member>
<member name="P:IFreeSql.Ado">
<summary>
数据库访问对象
</summary>
</member>
<member name="P:IFreeSql.Aop">
<summary>
所有拦截方法都在这里
</summary>
</member>
<member name="P:IFreeSql.CodeFirst">
<summary>
CodeFirst 模式开发相关方法
</summary>
</member>
<member name="P:IFreeSql.DbFirst">
<summary>
DbFirst 模式开发相关方法
</summary>
</member>
<member name="P:IFreeSql.GlobalFilter">
<summary>
全局过滤设置,可默认附加为 Select/Update/Delete 条件
</summary>
</member>
</members>
</doc> </doc>

View File

@ -134,7 +134,7 @@ namespace FreeSql.Internal.CommonProvider
public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict) public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
{ {
if (data == null) return; if (data == null) return;
if (typeof(T1) == typeof(object) && data.GetType() != table.Type) if (typeof(T1) == typeof(object) && new[] { table.Type, table.TypeLazy }.Contains(data.GetType()) == false)
throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。"); throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。");
foreach (var col in table.Columns.Values) foreach (var col in table.Columns.Values)
{ {

View File

@ -351,7 +351,7 @@ namespace FreeSql.Internal.CommonProvider
{ {
if (orm.Aop.AuditValueHandler == null) return; if (orm.Aop.AuditValueHandler == null) return;
if (data == null) return; if (data == null) return;
if (typeof(T1) == typeof(object) && data.GetType() != table.Type) if (typeof(T1) == typeof(object) && new[] { table.Type, table.TypeLazy }.Contains(data.GetType()) == false)
throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。"); throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。");
foreach (var col in table.Columns.Values) foreach (var col in table.Columns.Values)
{ {