mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 17:20:49 +08:00 
			
		
		
		
	- 调整 Aop 改为 event 事件;
- 调整 Ado.AopCommandExecuting/AopCommandExecuted 到 Aop.CommandBefore/After; - 增加 Aop.TraceBefore/After 事件;
This commit is contained in:
		@@ -34,7 +34,7 @@
 | 
			
		||||
	  <PackageReference Include="SafeObjectPool" Version="2.3.1" />
 | 
			
		||||
	  <PackageReference Include="System.ValueTuple" Version="4.5.0" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  <PropertyGroup Condition="'$(TargetFramework)' == 'net40'">
 | 
			
		||||
    <DefineConstants>net40</DefineConstants>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -2098,16 +2098,6 @@
 | 
			
		||||
            从库连接池
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAdo.AopCommandExecuting">
 | 
			
		||||
            <summary>
 | 
			
		||||
            监视数据库命令对象(执行前,调试)
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAdo.AopCommandExecuted">
 | 
			
		||||
            <summary>
 | 
			
		||||
            监视数据库命令对象(执行后,用于监视执行性能)
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAdo.DataType">
 | 
			
		||||
            <summary>
 | 
			
		||||
            数据库类型
 | 
			
		||||
@@ -2401,46 +2391,66 @@
 | 
			
		||||
            <param name="parms"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAop.ParseExpression">
 | 
			
		||||
        <member name="E:FreeSql.IAop.ParseExpression">
 | 
			
		||||
            <summary>
 | 
			
		||||
            可自定义解析表达式
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAop.ConfigEntity">
 | 
			
		||||
        <member name="E:FreeSql.IAop.ConfigEntity">
 | 
			
		||||
            <summary>
 | 
			
		||||
            自定义实体的配置,方便和多个 ORM 共同使用
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAop.ConfigEntityProperty">
 | 
			
		||||
        <member name="E:FreeSql.IAop.ConfigEntityProperty">
 | 
			
		||||
            <summary>
 | 
			
		||||
            自定义实体的属性配置,方便和多个 ORM 共同使用
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAop.CurdBefore">
 | 
			
		||||
        <member name="E:FreeSql.IAop.CurdBefore">
 | 
			
		||||
            <summary>
 | 
			
		||||
            增删查改,执行命令之前触发
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAop.CurdAfter">
 | 
			
		||||
        <member name="E:FreeSql.IAop.CurdAfter">
 | 
			
		||||
            <summary>
 | 
			
		||||
            增删查改,执行命令完成后触发
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAop.SyncStructureBefore">
 | 
			
		||||
        <member name="E:FreeSql.IAop.SyncStructureBefore">
 | 
			
		||||
            <summary>
 | 
			
		||||
            CodeFirst迁移,执行之前触发
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAop.SyncStructureAfter">
 | 
			
		||||
        <member name="E:FreeSql.IAop.SyncStructureAfter">
 | 
			
		||||
            <summary>
 | 
			
		||||
            CodeFirst迁移,执行完成触发
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.IAop.AuditValue">
 | 
			
		||||
        <member name="E:FreeSql.IAop.AuditValue">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Insert/Update自动值处理
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="E:FreeSql.IAop.CommandBefore">
 | 
			
		||||
            <summary>
 | 
			
		||||
            监视数据库命令对象(执行前,调试)
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="E:FreeSql.IAop.CommandAfter">
 | 
			
		||||
            <summary>
 | 
			
		||||
            监视数据库命令对象(执行后,用于监视执行性能)
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="E:FreeSql.IAop.TraceBefore">
 | 
			
		||||
            <summary>
 | 
			
		||||
            跟踪开始
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="E:FreeSql.IAop.TraceAfter">
 | 
			
		||||
            <summary>
 | 
			
		||||
            跟踪结束
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.ParseExpressionEventArgs.FreeParse">
 | 
			
		||||
            <summary>
 | 
			
		||||
            内置解析功能,可辅助您进行解析
 | 
			
		||||
@@ -2586,6 +2596,56 @@
 | 
			
		||||
            获取实体的属性值,也可以设置实体的属性新值
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.CommandBeforeEventArgs.Identifier">
 | 
			
		||||
            <summary>
 | 
			
		||||
            标识符,可将 CommandBefore 与 CommandAfter 进行匹配
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.CommandAfterEventArgs.Exception">
 | 
			
		||||
            <summary>
 | 
			
		||||
            发生的错误
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.CommandAfterEventArgs.Log">
 | 
			
		||||
            <summary>
 | 
			
		||||
            执行SQL命令,返回的结果
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.CommandAfterEventArgs.ElapsedTicks">
 | 
			
		||||
            <summary>
 | 
			
		||||
            耗时(单位:Ticks)
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.CommandAfterEventArgs.ElapsedMilliseconds">
 | 
			
		||||
            <summary>
 | 
			
		||||
            耗时(单位:毫秒)
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.TraceBeforeEventArgs.Identifier">
 | 
			
		||||
            <summary>
 | 
			
		||||
            标识符,可将 TraceBeforeEventArgs 与 TraceAfterEventArgs 进行匹配
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.TraceAfterEventArgs.Remark">
 | 
			
		||||
            <summary>
 | 
			
		||||
            备注
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.TraceAfterEventArgs.Exception">
 | 
			
		||||
            <summary>
 | 
			
		||||
            发生的错误
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.TraceAfterEventArgs.ElapsedTicks">
 | 
			
		||||
            <summary>
 | 
			
		||||
            耗时(单位:Ticks)
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.Aop.TraceAfterEventArgs.ElapsedMilliseconds">
 | 
			
		||||
            <summary>
 | 
			
		||||
            耗时(单位:毫秒)
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:FreeSql.ICodeFirst.IsAutoSyncStructure">
 | 
			
		||||
            <summary>
 | 
			
		||||
            【开发环境必备】自动同步实体结构到数据库,程序运行中检查实体表是否存在,然后创建或修改
 | 
			
		||||
 
 | 
			
		||||
@@ -248,9 +248,15 @@ namespace FreeSql
 | 
			
		||||
                ret.CodeFirst.IsNoneCommandParameter = _isNoneCommandParameter;
 | 
			
		||||
                ret.CodeFirst.IsGenerateCommandParameterWithLambda = _isGenerateCommandParameterWithLambda;
 | 
			
		||||
                ret.CodeFirst.IsLazyLoading = _isLazyLoading;
 | 
			
		||||
                var ado = ret.Ado as Internal.CommonProvider.AdoProvider;
 | 
			
		||||
                ado.AopCommandExecuting += _aopCommandExecuting;
 | 
			
		||||
                ado.AopCommandExecuted += _aopCommandExecuted;
 | 
			
		||||
 | 
			
		||||
                ret.Aop.CommandBefore += new EventHandler<Aop.CommandBeforeEventArgs>((s, e) =>
 | 
			
		||||
                {
 | 
			
		||||
                    _aopCommandExecuting(e.Command);
 | 
			
		||||
                });
 | 
			
		||||
                ret.Aop.CommandAfter += new EventHandler<Aop.CommandAfterEventArgs>((s, e) =>
 | 
			
		||||
                {
 | 
			
		||||
                    _aopCommandExecuted(e.Command, e.Log);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                //添加实体属性名全局AOP转换处理
 | 
			
		||||
                if (_entityPropertyConvertType != StringConvertType.None)
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,6 @@ namespace FreeSql
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        List<IObjectPool<DbConnection>> SlavePools { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 监视数据库命令对象(执行前,调试)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Action<DbCommand> AopCommandExecuting { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 监视数据库命令对象(执行后,用于监视执行性能)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Action<DbCommand, string> AopCommandExecuted { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 数据库类型
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        DataType DataType { get; }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,44 +15,75 @@ namespace FreeSql
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 可自定义解析表达式
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        EventHandler<Aop.ParseExpressionEventArgs> ParseExpression { get; set; }
 | 
			
		||||
        event EventHandler<Aop.ParseExpressionEventArgs> ParseExpression;
 | 
			
		||||
        EventHandler<Aop.ParseExpressionEventArgs> ParseExpressionHandler { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自定义实体的配置,方便和多个 ORM 共同使用
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        EventHandler<Aop.ConfigEntityEventArgs> ConfigEntity { get; set; }
 | 
			
		||||
        event EventHandler<Aop.ConfigEntityEventArgs> ConfigEntity;
 | 
			
		||||
        EventHandler<Aop.ConfigEntityEventArgs> ConfigEntityHandler { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自定义实体的属性配置,方便和多个 ORM 共同使用
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        EventHandler<Aop.ConfigEntityPropertyEventArgs> ConfigEntityProperty { get; set; }
 | 
			
		||||
        event EventHandler<Aop.ConfigEntityPropertyEventArgs> ConfigEntityProperty;
 | 
			
		||||
        EventHandler<Aop.ConfigEntityPropertyEventArgs> ConfigEntityPropertyHandler { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 增删查改,执行命令之前触发
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        EventHandler<Aop.CurdBeforeEventArgs> CurdBefore { get; set; }
 | 
			
		||||
        event EventHandler<Aop.CurdBeforeEventArgs> CurdBefore;
 | 
			
		||||
        EventHandler<Aop.CurdBeforeEventArgs> CurdBeforeHandler { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 增删查改,执行命令完成后触发
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        EventHandler<Aop.CurdAfterEventArgs> CurdAfter { get; set; }
 | 
			
		||||
        event EventHandler<Aop.CurdAfterEventArgs> CurdAfter;
 | 
			
		||||
        EventHandler<Aop.CurdAfterEventArgs> CurdAfterHandler { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// CodeFirst迁移,执行之前触发
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        EventHandler<Aop.SyncStructureBeforeEventArgs> SyncStructureBefore { get; set; }
 | 
			
		||||
        event EventHandler<Aop.SyncStructureBeforeEventArgs> SyncStructureBefore;
 | 
			
		||||
        EventHandler<Aop.SyncStructureBeforeEventArgs> SyncStructureBeforeHandler { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// CodeFirst迁移,执行完成触发
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        EventHandler<Aop.SyncStructureAfterEventArgs> SyncStructureAfter { get; set; }
 | 
			
		||||
        event EventHandler<Aop.SyncStructureAfterEventArgs> SyncStructureAfter;
 | 
			
		||||
        EventHandler<Aop.SyncStructureAfterEventArgs> SyncStructureAfterHandler { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Insert/Update自动值处理
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        EventHandler<Aop.AuditValueEventArgs> AuditValue { get; set; }
 | 
			
		||||
        event EventHandler<Aop.AuditValueEventArgs> AuditValue;
 | 
			
		||||
        EventHandler<Aop.AuditValueEventArgs> AuditValueHandler { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 监视数据库命令对象(执行前,调试)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        event EventHandler<Aop.CommandBeforeEventArgs> CommandBefore;
 | 
			
		||||
        EventHandler<Aop.CommandBeforeEventArgs> CommandBeforeHandler { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 监视数据库命令对象(执行后,用于监视执行性能)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        event EventHandler<Aop.CommandAfterEventArgs> CommandAfter;
 | 
			
		||||
        EventHandler<Aop.CommandAfterEventArgs> CommandAfterHandler { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 跟踪开始
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        event EventHandler<Aop.TraceBeforeEventArgs> TraceBefore;
 | 
			
		||||
        EventHandler<Aop.TraceBeforeEventArgs> TraceBeforeHandler { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 跟踪结束
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        event EventHandler<Aop.TraceAfterEventArgs> TraceAfter;
 | 
			
		||||
        EventHandler<Aop.TraceAfterEventArgs> TraceAfterHandler { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace FreeSql.Aop
 | 
			
		||||
{
 | 
			
		||||
    #region ParseExpression
 | 
			
		||||
    public class ParseExpressionEventArgs : EventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public ParseExpressionEventArgs(Expression expression, Func<Expression, string> freeParse)
 | 
			
		||||
@@ -75,6 +106,9 @@ namespace FreeSql.Aop
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Result { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    #region ConfigEntity/Property
 | 
			
		||||
    public class ConfigEntityEventArgs : EventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public ConfigEntityEventArgs(Type entityType)
 | 
			
		||||
@@ -119,7 +153,9 @@ namespace FreeSql.Aop
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ColumnAttribute ModifyResult { get; }
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    #region CurdBefore/After
 | 
			
		||||
    public class CurdBeforeEventArgs : EventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public CurdBeforeEventArgs(Type entityType, TableInfo table, CurdType curdType, string sql, DbParameter[] dbParms) :
 | 
			
		||||
@@ -155,7 +191,7 @@ namespace FreeSql.Aop
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 实体类型的元数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public TableInfo Table { get; set; }
 | 
			
		||||
        public TableInfo Table { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行的 SQL
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -183,7 +219,7 @@ namespace FreeSql.Aop
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行SQL命令,返回的结果
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public object ExecuteResult { get; set; }
 | 
			
		||||
        public object ExecuteResult { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 耗时(单位:Ticks)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -193,7 +229,9 @@ namespace FreeSql.Aop
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public long ElapsedMilliseconds => this.Stopwatch.ElapsedMilliseconds;
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    #region SyncStructureBefore/After
 | 
			
		||||
    public class SyncStructureBeforeEventArgs : EventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public SyncStructureBeforeEventArgs(Type[] entityTypes) :
 | 
			
		||||
@@ -246,7 +284,9 @@ namespace FreeSql.Aop
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public long ElapsedMilliseconds => this.Stopwatch.ElapsedMilliseconds;
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    #region AuditValue
 | 
			
		||||
    public class AuditValueEventArgs : EventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public AuditValueEventArgs(AuditValueType autoValueType, ColumnInfo column, PropertyInfo property, object value)
 | 
			
		||||
@@ -285,4 +325,111 @@ namespace FreeSql.Aop
 | 
			
		||||
        public bool IsChanged { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
    public enum AuditValueType { Update, Insert }
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    #region CommandBefore/After
 | 
			
		||||
    public class CommandBeforeEventArgs : EventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public CommandBeforeEventArgs(DbCommand command) :
 | 
			
		||||
            this(Guid.NewGuid(), new Stopwatch(), command)
 | 
			
		||||
        {
 | 
			
		||||
            this.Stopwatch.Start();
 | 
			
		||||
        }
 | 
			
		||||
        protected CommandBeforeEventArgs(Guid identifier, Stopwatch stopwatch, DbCommand command)
 | 
			
		||||
        {
 | 
			
		||||
            this.Identifier = identifier;
 | 
			
		||||
            this.Stopwatch = stopwatch;
 | 
			
		||||
            this.Command = command;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 标识符,可将 CommandBefore 与 CommandAfter 进行匹配
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Guid Identifier { get; protected set; }
 | 
			
		||||
        protected Stopwatch Stopwatch { get; }
 | 
			
		||||
        internal Stopwatch StopwatchInternal => Stopwatch;
 | 
			
		||||
        public DbCommand Command { get; }
 | 
			
		||||
    }
 | 
			
		||||
    public class CommandAfterEventArgs : CommandBeforeEventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public CommandAfterEventArgs(CommandBeforeEventArgs before, Exception exception, string log) :
 | 
			
		||||
            base(before.Identifier, before.StopwatchInternal, before.Command)
 | 
			
		||||
        {
 | 
			
		||||
            this.Exception = exception;
 | 
			
		||||
            this.Log = log;
 | 
			
		||||
            this.Stopwatch.Stop();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发生的错误
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Exception Exception { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行SQL命令,返回的结果
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Log { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 耗时(单位:Ticks)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public long ElapsedTicks => this.Stopwatch.ElapsedTicks;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 耗时(单位:毫秒)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public long ElapsedMilliseconds => this.Stopwatch.ElapsedMilliseconds;
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    #region TraceBefore/After
 | 
			
		||||
    public class TraceBeforeEventArgs : EventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public TraceBeforeEventArgs(string operation, object value) :
 | 
			
		||||
            this(Guid.NewGuid(), new Stopwatch(), operation, value)
 | 
			
		||||
        {
 | 
			
		||||
            this.Stopwatch.Start();
 | 
			
		||||
        }
 | 
			
		||||
        protected TraceBeforeEventArgs(Guid identifier, Stopwatch stopwatch, string operation, object value)
 | 
			
		||||
        {
 | 
			
		||||
            this.Identifier = identifier;
 | 
			
		||||
            this.Stopwatch = stopwatch;
 | 
			
		||||
            this.Operation = operation;
 | 
			
		||||
            this.Value = value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 标识符,可将 TraceBeforeEventArgs 与 TraceAfterEventArgs 进行匹配
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Guid Identifier { get; protected set; }
 | 
			
		||||
        protected Stopwatch Stopwatch { get; }
 | 
			
		||||
        internal Stopwatch StopwatchInternal => Stopwatch;
 | 
			
		||||
        public string Operation { get; }
 | 
			
		||||
        public object Value { get; }
 | 
			
		||||
    }
 | 
			
		||||
    public class TraceAfterEventArgs : TraceBeforeEventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public TraceAfterEventArgs(TraceBeforeEventArgs before, string remark, Exception exception) :
 | 
			
		||||
            base(before.Identifier, before.StopwatchInternal, before.Operation, before.Value)
 | 
			
		||||
        {
 | 
			
		||||
            this.Remark = remark;
 | 
			
		||||
            this.Exception = exception;
 | 
			
		||||
            this.Stopwatch.Stop();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 备注
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Remark { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发生的错误
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Exception Exception { get; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 耗时(单位:Ticks)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public long ElapsedTicks => this.Stopwatch.ElapsedTicks;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 耗时(单位:毫秒)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public long ElapsedMilliseconds => this.Stopwatch.ElapsedMilliseconds;
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
}
 | 
			
		||||
@@ -486,7 +486,9 @@ namespace FreeSql.Internal
 | 
			
		||||
            if (isLeftMapType) oldMapType = tsc.SetMapTypeReturnOld(leftMapColumn.Attribute.MapType);
 | 
			
		||||
            
 | 
			
		||||
            var right = ExpressionLambdaToSql(rightExp, tsc);
 | 
			
		||||
            if (right != "NULL" && isLeftMapType)
 | 
			
		||||
            if (right != "NULL" && isLeftMapType && 
 | 
			
		||||
                //判断参数化后的bug
 | 
			
		||||
                !(right.Contains('@') || right.Contains('?') || right.Contains(':')))
 | 
			
		||||
            {
 | 
			
		||||
                var enumType = leftMapColumn.CsType.NullableTypeOrThis();
 | 
			
		||||
                if (enumType.IsEnum)
 | 
			
		||||
@@ -500,7 +502,9 @@ namespace FreeSql.Internal
 | 
			
		||||
                {
 | 
			
		||||
                    oldMapType = tsc.SetMapTypeReturnOld(rightMapColumn.Attribute.MapType);
 | 
			
		||||
                    left = ExpressionLambdaToSql(leftExp, tsc);
 | 
			
		||||
                    if (left != "NULL" && isRightMapType)
 | 
			
		||||
                    if (left != "NULL" && isRightMapType &&
 | 
			
		||||
                        //判断参数化后的bug
 | 
			
		||||
                        !(left.Contains('@') || left.Contains('?') || left.Contains(':')))
 | 
			
		||||
                    {
 | 
			
		||||
                        var enumType = rightMapColumn.CsType.NullableTypeOrThis();
 | 
			
		||||
                        if (enumType.IsEnum)
 | 
			
		||||
@@ -560,10 +564,10 @@ namespace FreeSql.Internal
 | 
			
		||||
        {
 | 
			
		||||
            if (exp == null) return "";
 | 
			
		||||
            if (tsc.dbParams != null && tsc.mapColumnTmp != null && tsc.mapColumnTmp.CsType.NullableTypeOrThis() != exp.Type) tsc.SetMapColumnTmp(null);
 | 
			
		||||
            if (tsc.isDisableDiyParse == false && _common._orm.Aop.ParseExpression != null)
 | 
			
		||||
            if (tsc.isDisableDiyParse == false && _common._orm.Aop.ParseExpressionHandler != null)
 | 
			
		||||
            {
 | 
			
		||||
                var args = new Aop.ParseExpressionEventArgs(exp, ukexp => ExpressionLambdaToSql(ukexp, tsc.CloneDisableDiyParse()));
 | 
			
		||||
                _common._orm.Aop.ParseExpression?.Invoke(this, args);
 | 
			
		||||
                _common._orm.Aop.ParseExpressionHandler?.Invoke(this, args);
 | 
			
		||||
                if (string.IsNullOrEmpty(args.Result) == false) return args.Result;
 | 
			
		||||
            }
 | 
			
		||||
            switch (exp.NodeType)
 | 
			
		||||
 
 | 
			
		||||
@@ -17,10 +17,8 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        protected abstract void ReturnConnection(IObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex);
 | 
			
		||||
        protected abstract DbCommand CreateCommand();
 | 
			
		||||
        protected abstract DbParameter[] GetDbParamtersByObject(string sql, object obj);
 | 
			
		||||
        public Action<DbCommand> AopCommandExecuting { get; set; }
 | 
			
		||||
        public Action<DbCommand, string> AopCommandExecuted { get; set; }
 | 
			
		||||
 | 
			
		||||
        protected bool IsTracePerformance => AopCommandExecuted != null;
 | 
			
		||||
        protected bool IsTracePerformance => _util?._orm?.Aop.CommandAfterHandler != null;
 | 
			
		||||
 | 
			
		||||
        public IObjectPool<DbConnection> MasterPool { get; protected set; }
 | 
			
		||||
        public List<IObjectPool<DbConnection>> SlavePools { get; } = new List<IObjectPool<DbConnection>>();
 | 
			
		||||
@@ -35,22 +33,22 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            this.DataType = dataType;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void LoggerException(IObjectPool<DbConnection> pool, (DbCommand cmd, bool isclose) pc, Exception e, DateTime dt, StringBuilder logtxt, bool isThrowException = true)
 | 
			
		||||
        void LoggerException(IObjectPool<DbConnection> pool, (Aop.CommandBeforeEventArgs before, DbCommand cmd, bool isclose) pc, Exception ex, DateTime dt, StringBuilder logtxt, bool isThrowException = true)
 | 
			
		||||
        {
 | 
			
		||||
            var cmd = pc.cmd;
 | 
			
		||||
            if (pc.isclose) pc.cmd.Connection.Close();
 | 
			
		||||
            if (IsTracePerformance)
 | 
			
		||||
            {
 | 
			
		||||
                TimeSpan ts = DateTime.Now.Subtract(dt);
 | 
			
		||||
                if (e == null && ts.TotalMilliseconds > 100)
 | 
			
		||||
                if (ex == null && ts.TotalMilliseconds > 100)
 | 
			
		||||
                    Trace.WriteLine(logtxt.Insert(0, $"{pool?.Policy.Name}(执行SQL)语句耗时过长{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n").ToString());
 | 
			
		||||
                else
 | 
			
		||||
                    logtxt.Insert(0, $"{pool?.Policy.Name}(执行SQL)耗时{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n").ToString();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (e == null)
 | 
			
		||||
            if (ex == null)
 | 
			
		||||
            {
 | 
			
		||||
                AopCommandExecuted?.Invoke(cmd, logtxt.ToString());
 | 
			
		||||
                _util?._orm?.Aop.CommandAfterHandler?.Invoke(_util._orm, new Aop.CommandAfterEventArgs(pc.before, null, logtxt.ToString()));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -59,7 +57,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            foreach (DbParameter parm in cmd.Parameters)
 | 
			
		||||
                log.Append(parm.ParameterName.PadRight(20, ' ')).Append(" = ").Append((parm.Value ?? DBNull.Value) == DBNull.Value ? "NULL" : parm.Value).Append("\r\n");
 | 
			
		||||
 | 
			
		||||
            log.Append(e.Message);
 | 
			
		||||
            log.Append(ex.Message);
 | 
			
		||||
            Trace.WriteLine(log.ToString());
 | 
			
		||||
 | 
			
		||||
            if (cmd.Transaction != null)
 | 
			
		||||
@@ -70,16 +68,16 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                    //cmd.Transaction.Rollback();
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    RollbackTransaction();
 | 
			
		||||
                    RollbackTransaction(ex);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            AopCommandExecuted?.Invoke(cmd, log.ToString());
 | 
			
		||||
            _util?._orm?.Aop.CommandAfterHandler?.Invoke(_util._orm, new Aop.CommandAfterEventArgs(pc.before, null, logtxt.ToString()));
 | 
			
		||||
 | 
			
		||||
            cmd.Parameters.Clear();
 | 
			
		||||
            if (isThrowException)
 | 
			
		||||
            {
 | 
			
		||||
                if (DataType == DataType.Sqlite) cmd.Dispose();
 | 
			
		||||
                throw e;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -547,11 +545,14 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
 | 
			
		||||
            Object<DbConnection> conn = null;
 | 
			
		||||
            var pc = PrepareCommand(connection, transaction, cmdType, cmdText, cmdParms, logtxt);
 | 
			
		||||
            if (IsTracePerformance) logtxt.Append("PrepareCommand: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
            if (IsTracePerformance)
 | 
			
		||||
            {
 | 
			
		||||
                logtxt.Append("PrepareCommand: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                logtxt_dt = DateTime.Now;
 | 
			
		||||
            }
 | 
			
		||||
            Exception ex = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                if (isSlave)
 | 
			
		||||
                {
 | 
			
		||||
                    //从库查询切换,恢复
 | 
			
		||||
@@ -571,7 +572,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                        {
 | 
			
		||||
                            if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                            ReturnConnection(pool, conn, ex); //pool.Return(conn, ex);
 | 
			
		||||
                            if (IsTracePerformance) logtxt.Append("ReleaseConnection: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                            if (IsTracePerformance) logtxt.Append("Pool.Return: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                        }
 | 
			
		||||
                        LoggerException(pool, pc, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false);
 | 
			
		||||
                        pc.cmd.Parameters.Clear();
 | 
			
		||||
@@ -587,43 +588,31 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                }
 | 
			
		||||
                if (IsTracePerformance)
 | 
			
		||||
                {
 | 
			
		||||
                    logtxt.Append("Open: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    logtxt.Append("Pool.Get: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    logtxt_dt = DateTime.Now;
 | 
			
		||||
                }
 | 
			
		||||
                using (var dr = pc.cmd.ExecuteReader())
 | 
			
		||||
                {
 | 
			
		||||
                    if (IsTracePerformance) logtxt.Append("ExecuteReader: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    int resultIndex = 0;
 | 
			
		||||
                    while (true)
 | 
			
		||||
                    {
 | 
			
		||||
                        while (true)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                            bool isread = dr.Read();
 | 
			
		||||
                            if (IsTracePerformance) logtxt.Append("	dr.Read: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                            if (isread == false) break;
 | 
			
		||||
 | 
			
		||||
                            if (readerHander != null)
 | 
			
		||||
                            {
 | 
			
		||||
                                object[] values = null;
 | 
			
		||||
                                if (IsTracePerformance)
 | 
			
		||||
                                {
 | 
			
		||||
                                    logtxt_dt = DateTime.Now;
 | 
			
		||||
                                    values = new object[dr.FieldCount];
 | 
			
		||||
                                    dr.GetValues(values);
 | 
			
		||||
                                    logtxt.Append("	dr.GetValues: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                                    logtxt_dt = DateTime.Now;
 | 
			
		||||
                                }
 | 
			
		||||
                                readerHander(dr, resultIndex);
 | 
			
		||||
                                if (IsTracePerformance) logtxt.Append("	readerHander: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms (").Append(string.Join(", ", values)).Append(")\r\n");
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        if (++resultIndex >= multipleResult || dr.NextResult() == false) break;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                    dr.Close();
 | 
			
		||||
                }
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("ExecuteReader_dispose: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                if (IsTracePerformance)
 | 
			
		||||
                {
 | 
			
		||||
                    logtxt.Append("ExecuteReader: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    logtxt_dt = DateTime.Now;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex2)
 | 
			
		||||
            {
 | 
			
		||||
@@ -632,9 +621,12 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
 | 
			
		||||
            if (conn != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                ReturnConnection(pool, conn, ex); //pool.Return(conn, ex);
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("ReleaseConnection: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                if (IsTracePerformance)
 | 
			
		||||
                {
 | 
			
		||||
                    logtxt.Append("Pool.Return: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                    logtxt_dt = DateTime.Now;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(pool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
@@ -735,7 +727,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            {
 | 
			
		||||
                if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                ReturnConnection(MasterPool, conn, ex); //this.MasterPool.Return(conn, ex);
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("ReleaseConnection: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("Pool.Return: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(this.MasterPool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
@@ -771,7 +763,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            {
 | 
			
		||||
                if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                ReturnConnection(MasterPool, conn, ex); //this.MasterPool.Return(conn, ex);
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("ReleaseConnection: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("Pool.Return: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(this.MasterPool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
@@ -779,7 +771,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        (DbCommand cmd, bool isclose) PrepareCommand(DbConnection connection, DbTransaction transaction, CommandType cmdType, string cmdText, DbParameter[] cmdParms, StringBuilder logtxt)
 | 
			
		||||
        (Aop.CommandBeforeEventArgs before, DbCommand cmd, bool isclose) PrepareCommand(DbConnection connection, DbTransaction transaction, CommandType cmdType, string cmdText, DbParameter[] cmdParms, StringBuilder logtxt)
 | 
			
		||||
        {
 | 
			
		||||
            var dt = DateTime.Now;
 | 
			
		||||
            DbCommand cmd = CreateCommand();
 | 
			
		||||
@@ -800,14 +792,10 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (connection == null)
 | 
			
		||||
            {
 | 
			
		||||
                var tran = transaction ?? TransactionCurrentThread;
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("	PrepareCommand_part1: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms cmdParms: ").Append(cmd.Parameters.Count).Append("\r\n");
 | 
			
		||||
 | 
			
		||||
                if (tran != null && connection == null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (IsTracePerformance) dt = DateTime.Now;
 | 
			
		||||
                    cmd.Connection = tran.Connection;
 | 
			
		||||
                    cmd.Transaction = tran;
 | 
			
		||||
                    if (IsTracePerformance) logtxt.Append("	PrepareCommand_tran!=null: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
@@ -825,11 +813,12 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (IsTracePerformance) dt = DateTime.Now;
 | 
			
		||||
            AutoCommitTransaction();
 | 
			
		||||
            if (IsTracePerformance) logtxt.Append("   AutoCommitTransaction: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
            CommitTimeoutTransaction();
 | 
			
		||||
            if (IsTracePerformance) logtxt.Append("   CommitTimeoutTransaction: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
 | 
			
		||||
            AopCommandExecuting?.Invoke(cmd);
 | 
			
		||||
            return (cmd, isclose);
 | 
			
		||||
            var before = new Aop.CommandBeforeEventArgs(cmd);
 | 
			
		||||
            _util?._orm?.Aop.CommandBeforeHandler?.Invoke(_util._orm, before);
 | 
			
		||||
            return (before, cmd, isclose);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -476,11 +476,14 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
 | 
			
		||||
            Object<DbConnection> conn = null;
 | 
			
		||||
            var pc = await PrepareCommandAsync(connection, transaction, cmdType, cmdText, cmdParms, logtxt);
 | 
			
		||||
            if (IsTracePerformance) logtxt.Append("PrepareCommandAsync: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
            if (IsTracePerformance)
 | 
			
		||||
            {
 | 
			
		||||
                logtxt.Append("PrepareCommand: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                logtxt_dt = DateTime.Now;
 | 
			
		||||
            }
 | 
			
		||||
            Exception ex = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                if (isSlave)
 | 
			
		||||
                {
 | 
			
		||||
                    //从库查询切换,恢复
 | 
			
		||||
@@ -500,7 +503,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                        {
 | 
			
		||||
                            if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                            ReturnConnection(pool, conn, ex); //pool.Return(conn, ex);
 | 
			
		||||
                            if (IsTracePerformance) logtxt.Append("ReleaseConnection: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                            if (IsTracePerformance) logtxt.Append("Pool.Return: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                        }
 | 
			
		||||
                        LoggerException(pool, pc, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false);
 | 
			
		||||
                        pc.cmd.Parameters.Clear();
 | 
			
		||||
@@ -516,43 +519,31 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                }
 | 
			
		||||
                if (IsTracePerformance)
 | 
			
		||||
                {
 | 
			
		||||
                    logtxt.Append("OpenAsync: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    logtxt.Append("Pool.Get: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    logtxt_dt = DateTime.Now;
 | 
			
		||||
                }
 | 
			
		||||
                using (var dr = await pc.cmd.ExecuteReaderAsync())
 | 
			
		||||
                {
 | 
			
		||||
                    if (IsTracePerformance) logtxt.Append("ExecuteReaderAsync: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    int resultIndex = 0;
 | 
			
		||||
                    while (true)
 | 
			
		||||
                    {
 | 
			
		||||
                        while (true)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                            bool isread = await dr.ReadAsync();
 | 
			
		||||
                            if (IsTracePerformance) logtxt.Append("	dr.ReadAsync: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                            if (isread == false) break;
 | 
			
		||||
 | 
			
		||||
                            if (readerHander != null)
 | 
			
		||||
                            {
 | 
			
		||||
                                object[] values = null;
 | 
			
		||||
                                if (IsTracePerformance)
 | 
			
		||||
                                {
 | 
			
		||||
                                    logtxt_dt = DateTime.Now;
 | 
			
		||||
                                    values = new object[dr.FieldCount];
 | 
			
		||||
                                    for (int a = 0; a < values.Length; a++) if (!await dr.IsDBNullAsync(a)) values[a] = await dr.GetFieldValueAsync<object>(a);
 | 
			
		||||
                                    logtxt.Append("	dr.GetValues: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                                    logtxt_dt = DateTime.Now;
 | 
			
		||||
                                }
 | 
			
		||||
                                await readerHander(dr, resultIndex);
 | 
			
		||||
                                if (IsTracePerformance) logtxt.Append("	readerHanderAsync: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms (").Append(string.Join(", ", values)).Append(")\r\n");
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        if (++resultIndex >= multipleResult || dr.NextResult() == false) break;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                    dr.Close();
 | 
			
		||||
                }
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("ExecuteReaderAsync_dispose: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                if (IsTracePerformance)
 | 
			
		||||
                {
 | 
			
		||||
                    logtxt.Append("ExecuteReader: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    logtxt_dt = DateTime.Now;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex2)
 | 
			
		||||
            {
 | 
			
		||||
@@ -563,7 +554,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            {
 | 
			
		||||
                if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                ReturnConnection(pool, conn, ex); //pool.Return(conn, ex);
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("ReleaseConnection: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("Pool.Return: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(pool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
@@ -665,7 +656,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            {
 | 
			
		||||
                if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                ReturnConnection(MasterPool, conn, ex); //this.MasterPool.Return(conn, ex);
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("ReleaseConnection: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("Pool.Return: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(this.MasterPool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
@@ -701,7 +692,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            {
 | 
			
		||||
                if (IsTracePerformance) logtxt_dt = DateTime.Now;
 | 
			
		||||
                ReturnConnection(MasterPool, conn, ex); //this.MasterPool.Return(conn, ex);
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("ReleaseConnection: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
                if (IsTracePerformance) logtxt.Append("Pool.Return: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms");
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(this.MasterPool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
@@ -709,7 +700,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        async Task<(DbCommand cmd, bool isclose)> PrepareCommandAsync(DbConnection connection, DbTransaction transaction, CommandType cmdType, string cmdText, DbParameter[] cmdParms, StringBuilder logtxt)
 | 
			
		||||
        async Task<(Aop.CommandBeforeEventArgs before, DbCommand cmd, bool isclose)> PrepareCommandAsync(DbConnection connection, DbTransaction transaction, CommandType cmdType, string cmdText, DbParameter[] cmdParms, StringBuilder logtxt)
 | 
			
		||||
        {
 | 
			
		||||
            DateTime dt = DateTime.Now;
 | 
			
		||||
            DbCommand cmd = CreateCommand();
 | 
			
		||||
@@ -733,10 +724,8 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
 | 
			
		||||
                if (tran != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (IsTracePerformance) dt = DateTime.Now;
 | 
			
		||||
                    cmd.Connection = tran.Connection;
 | 
			
		||||
                    cmd.Transaction = tran;
 | 
			
		||||
                    if (IsTracePerformance) logtxt.Append("	PrepareCommandAsync_tran!=null: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
@@ -745,7 +734,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                {
 | 
			
		||||
                    if (IsTracePerformance) dt = DateTime.Now;
 | 
			
		||||
                    await connection.OpenAsync();
 | 
			
		||||
                    if (IsTracePerformance) logtxt.Append("	PrepareCommand_ConnectionOpenAsync: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    if (IsTracePerformance) logtxt.Append("	PrepareCommand_ConnectionOpen: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
 | 
			
		||||
                    isclose = true;
 | 
			
		||||
                }
 | 
			
		||||
                cmd.Connection = connection;
 | 
			
		||||
@@ -753,10 +742,9 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                    cmd.Transaction = transaction;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (IsTracePerformance) logtxt.Append("	PrepareCommandAsync ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms cmdParms: ").Append(cmd.Parameters.Count).Append("\r\n");
 | 
			
		||||
 | 
			
		||||
            AopCommandExecuting?.Invoke(cmd);
 | 
			
		||||
            return (cmd, isclose);
 | 
			
		||||
            var before = new Aop.CommandBeforeEventArgs(cmd);
 | 
			
		||||
            _util?._orm?.Aop.CommandBeforeHandler?.Invoke(_util._orm, before);
 | 
			
		||||
            return (before, cmd, isclose);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
 | 
			
		||||
        class Transaction2
 | 
			
		||||
        {
 | 
			
		||||
            internal Aop.TraceBeforeEventArgs AopBefore;
 | 
			
		||||
            internal Object<DbConnection> Conn;
 | 
			
		||||
            internal DbTransaction Transaction;
 | 
			
		||||
            internal DateTime RunTime;
 | 
			
		||||
@@ -33,6 +34,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        private object _trans_lock = new object();
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
        public void BeginTransaction(TimeSpan timeout, IsolationLevel? isolationLevel)
 | 
			
		||||
        {
 | 
			
		||||
@@ -41,16 +43,21 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            int tid = Thread.CurrentThread.ManagedThreadId;
 | 
			
		||||
            Transaction2 tran = null;
 | 
			
		||||
            Object<DbConnection> conn = null;
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("ThreadTransaction", isolationLevel);
 | 
			
		||||
            _util?._orm?.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                conn = MasterPool.Get();
 | 
			
		||||
                tran = new Transaction2(conn, isolationLevel == null ? conn.Value.BeginTransaction() : conn.Value.BeginTransaction(isolationLevel.Value), timeout);
 | 
			
		||||
                tran.AopBefore = before;
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                Trace.WriteLine($"数据库出错(开启事务){ex.Message} \r\n{ex.StackTrace}");
 | 
			
		||||
                MasterPool.Return(conn);
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, "", ex);
 | 
			
		||||
                _util?._orm?.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            if (_trans.ContainsKey(tid)) CommitTransaction();
 | 
			
		||||
@@ -59,17 +66,17 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                _trans.TryAdd(tid, tran);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AutoCommitTransaction()
 | 
			
		||||
        private void CommitTimeoutTransaction()
 | 
			
		||||
        {
 | 
			
		||||
            if (_trans.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
                Transaction2[] trans = null;
 | 
			
		||||
                lock (_trans_lock)
 | 
			
		||||
                    trans = _trans.Values.Where(st2 => DateTime.Now.Subtract(st2.RunTime) > st2.Timeout).ToArray();
 | 
			
		||||
                foreach (Transaction2 tran in trans) CommitTransaction(true, tran);
 | 
			
		||||
                foreach (Transaction2 tran in trans) CommitTransaction(true, tran, null, "Timeout自动提交");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private void CommitTransaction(bool isCommit, Transaction2 tran)
 | 
			
		||||
        private void CommitTransaction(bool isCommit, Transaction2 tran, Exception rollbackException, string remark = null)
 | 
			
		||||
        {
 | 
			
		||||
            if (tran == null || tran.Transaction == null || tran.Transaction.Connection == null) return;
 | 
			
		||||
 | 
			
		||||
@@ -79,29 +86,34 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                        _trans.TryRemove(tran.Conn.LastGetThreadId, out var oldtran);
 | 
			
		||||
 | 
			
		||||
            Exception ex = null;
 | 
			
		||||
            var f001 = isCommit ? "提交" : "回滚";
 | 
			
		||||
            if (string.IsNullOrEmpty(remark)) remark = isCommit ? "提交" : "回滚";
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                Trace.WriteLine($"线程{tran.Conn.LastGetThreadId}事务{f001}");
 | 
			
		||||
                Trace.WriteLine($"线程{tran.Conn.LastGetThreadId}事务{remark}");
 | 
			
		||||
                if (isCommit) tran.Transaction.Commit();
 | 
			
		||||
                else tran.Transaction.Rollback();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex2)
 | 
			
		||||
            {
 | 
			
		||||
                ex = ex2;
 | 
			
		||||
                Trace.WriteLine($"数据库出错({f001}事务):{ex.Message} {ex.StackTrace}");
 | 
			
		||||
                Trace.WriteLine($"数据库出错({remark}事务):{ex.Message} {ex.StackTrace}");
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                ReturnConnection(MasterPool, tran.Conn, ex); //MasterPool.Return(tran.Conn, ex);
 | 
			
		||||
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(tran.AopBefore, remark, ex ?? rollbackException);
 | 
			
		||||
                _util?._orm?.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private void CommitTransaction(bool isCommit)
 | 
			
		||||
        public void CommitTransaction()
 | 
			
		||||
        {
 | 
			
		||||
            if (_trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var tran)) CommitTransaction(isCommit, tran);
 | 
			
		||||
            if (_trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var tran)) CommitTransaction(true, tran, null);
 | 
			
		||||
        }
 | 
			
		||||
        public void RollbackTransaction(Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            if (_trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var tran)) CommitTransaction(false, tran, ex);
 | 
			
		||||
        }
 | 
			
		||||
        public void CommitTransaction() => CommitTransaction(true);
 | 
			
		||||
        public void RollbackTransaction() => CommitTransaction(false);
 | 
			
		||||
 | 
			
		||||
        public void Transaction(Action handler) => TransactionInternal(null, TimeSpan.FromSeconds(60), handler);
 | 
			
		||||
        public void Transaction(TimeSpan timeout, Action handler) => TransactionInternal(null, timeout, handler);
 | 
			
		||||
@@ -117,7 +129,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                RollbackTransaction();
 | 
			
		||||
                RollbackTransaction(ex);
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -132,7 +144,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                Transaction2[] trans = null;
 | 
			
		||||
                lock (_trans_lock)
 | 
			
		||||
                    trans = _trans.Values.ToArray();
 | 
			
		||||
                foreach (Transaction2 tran in trans) CommitTransaction(false, tran);
 | 
			
		||||
                foreach (Transaction2 tran in trans) CommitTransaction(false, tran, null, "Dispose自动提交");
 | 
			
		||||
            }
 | 
			
		||||
            catch { }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,13 +8,38 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
{
 | 
			
		||||
    public class AopProvider : IAop
 | 
			
		||||
    {
 | 
			
		||||
        public EventHandler<Aop.ParseExpressionEventArgs> ParseExpression { get; set; }
 | 
			
		||||
        public EventHandler<Aop.ConfigEntityEventArgs> ConfigEntity { get; set; }
 | 
			
		||||
        public EventHandler<Aop.ConfigEntityPropertyEventArgs> ConfigEntityProperty { get; set; }
 | 
			
		||||
        public EventHandler<Aop.CurdBeforeEventArgs> CurdBefore { get; set; }
 | 
			
		||||
        public EventHandler<Aop.CurdAfterEventArgs> CurdAfter { get; set; }
 | 
			
		||||
        public EventHandler<Aop.SyncStructureBeforeEventArgs> SyncStructureBefore { get; set; }
 | 
			
		||||
        public EventHandler<Aop.SyncStructureAfterEventArgs> SyncStructureAfter { get; set; }
 | 
			
		||||
        public EventHandler<Aop.AuditValueEventArgs> AuditValue { get; set; }
 | 
			
		||||
        public event EventHandler<Aop.ParseExpressionEventArgs> ParseExpression;
 | 
			
		||||
        public event EventHandler<Aop.ConfigEntityEventArgs> ConfigEntity;
 | 
			
		||||
        public event EventHandler<Aop.ConfigEntityPropertyEventArgs> ConfigEntityProperty;
 | 
			
		||||
 | 
			
		||||
        public event EventHandler<Aop.CurdBeforeEventArgs> CurdBefore;
 | 
			
		||||
        public event EventHandler<Aop.CurdAfterEventArgs> CurdAfter;
 | 
			
		||||
        public event EventHandler<Aop.SyncStructureBeforeEventArgs> SyncStructureBefore;
 | 
			
		||||
        public event EventHandler<Aop.SyncStructureAfterEventArgs> SyncStructureAfter;
 | 
			
		||||
 | 
			
		||||
        public event EventHandler<Aop.AuditValueEventArgs> AuditValue;
 | 
			
		||||
 | 
			
		||||
        public event EventHandler<Aop.CommandBeforeEventArgs> CommandBefore;
 | 
			
		||||
        public event EventHandler<Aop.CommandAfterEventArgs> CommandAfter;
 | 
			
		||||
        public event EventHandler<Aop.TraceBeforeEventArgs> TraceBefore;
 | 
			
		||||
        public event EventHandler<Aop.TraceAfterEventArgs> TraceAfter;
 | 
			
		||||
 | 
			
		||||
        //------------- Handler
 | 
			
		||||
 | 
			
		||||
        public EventHandler<Aop.ParseExpressionEventArgs> ParseExpressionHandler => ParseExpression;
 | 
			
		||||
        public EventHandler<Aop.ConfigEntityEventArgs> ConfigEntityHandler => ConfigEntity;
 | 
			
		||||
        public EventHandler<Aop.ConfigEntityPropertyEventArgs> ConfigEntityPropertyHandler => ConfigEntityProperty;
 | 
			
		||||
 | 
			
		||||
        public EventHandler<Aop.CurdBeforeEventArgs> CurdBeforeHandler => CurdBefore;
 | 
			
		||||
        public EventHandler<Aop.CurdAfterEventArgs> CurdAfterHandler => CurdAfter;
 | 
			
		||||
        public EventHandler<Aop.SyncStructureBeforeEventArgs> SyncStructureBeforeHandler => SyncStructureBefore;
 | 
			
		||||
        public EventHandler<Aop.SyncStructureAfterEventArgs> SyncStructureAfterHandler => SyncStructureAfter;
 | 
			
		||||
 | 
			
		||||
        public EventHandler<Aop.AuditValueEventArgs> AuditValueHandler => AuditValue;
 | 
			
		||||
 | 
			
		||||
        public EventHandler<Aop.CommandBeforeEventArgs> CommandBeforeHandler => CommandBefore;
 | 
			
		||||
        public EventHandler<Aop.CommandAfterEventArgs> CommandAfterHandler => CommandAfter;
 | 
			
		||||
        public EventHandler<Aop.TraceBeforeEventArgs> TraceBeforeHandler => TraceBefore;
 | 
			
		||||
        public EventHandler<Aop.TraceAfterEventArgs> TraceAfterHandler => TraceAfter;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                .Select(a => (a.entityType, GetTableNameLowerOrUpper(a.tableName))).ToArray();
 | 
			
		||||
            if (syncObjects.Any() == false) return false;
 | 
			
		||||
            var before = new Aop.SyncStructureBeforeEventArgs(syncObjects.Select(a => a.entityType).ToArray());
 | 
			
		||||
            _orm.Aop.SyncStructureBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.SyncStructureBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            string ddl = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -110,7 +110,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception);
 | 
			
		||||
                _orm.Aop.SyncStructureAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.SyncStructureAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (string.IsNullOrEmpty(sql)) return 0;
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var affrows = 0;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -78,7 +78,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            this.ClearData();
 | 
			
		||||
            return affrows;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (string.IsNullOrEmpty(sql)) return 0;
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var affrows = 0;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -34,7 +34,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            this.ClearData();
 | 
			
		||||
            return affrows;
 | 
			
		||||
 
 | 
			
		||||
@@ -121,7 +121,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                source = source.Where(a => a != null).ToList();
 | 
			
		||||
                AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
 | 
			
		||||
                _source.AddRange(source);
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
@@ -151,10 +151,10 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (orm.Aop.AuditValue != null)
 | 
			
		||||
                if (orm.Aop.AuditValueHandler != null)
 | 
			
		||||
                {
 | 
			
		||||
                    var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Insert, col, table.Properties[col.CsName], val);
 | 
			
		||||
                    orm.Aop.AuditValue(sender, auditArgs);
 | 
			
		||||
                    orm.Aop.AuditValueHandler(sender, auditArgs);
 | 
			
		||||
                    if (auditArgs.IsChanged)
 | 
			
		||||
                    {
 | 
			
		||||
                        col.SetMapValue(data, val = auditArgs.Value);
 | 
			
		||||
@@ -208,35 +208,55 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteAffrows", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    ret += this.RawExecuteAffrows();
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        ret += this.RawExecuteAffrows();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                ret += this.RawExecuteAffrows();
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            ret += this.RawExecuteAffrows();
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
@@ -260,37 +280,57 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteIdentity", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    if (a < ss.Length - 1) this.RawExecuteAffrows();
 | 
			
		||||
                    else ret = this.RawExecuteIdentity();
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        if (a < ss.Length - 1) this.RawExecuteAffrows();
 | 
			
		||||
                        else ret = this.RawExecuteIdentity();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                if (a < ss.Length - 1) this.RawExecuteAffrows();
 | 
			
		||||
                                else ret = this.RawExecuteIdentity();
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            if (a < ss.Length - 1) this.RawExecuteAffrows();
 | 
			
		||||
                            else ret = this.RawExecuteIdentity();
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
@@ -314,35 +354,55 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteInserted", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    ret.AddRange(this.RawExecuteInserted());
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        ret.AddRange(this.RawExecuteInserted());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                ret.AddRange(this.RawExecuteInserted());
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            ret.AddRange(this.RawExecuteInserted());
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
@@ -353,7 +413,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        {
 | 
			
		||||
            var sql = ToSql();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var affrows = 0;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -368,7 +428,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return affrows;
 | 
			
		||||
        }
 | 
			
		||||
@@ -507,4 +567,3 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,35 +34,55 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteAffrowsAsync", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    ret += await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        ret += await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                ret += await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            ret += await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
@@ -86,42 +106,62 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteIdentityAsync", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    if (a < ss.Length - 1) await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                    else ret = await this.RawExecuteIdentityAsync();
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        if (a < ss.Length - 1) await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                        else ret = await this.RawExecuteIdentityAsync();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                if (a < ss.Length - 1) await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                                else ret = await this.RawExecuteIdentityAsync();
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            if (a < ss.Length - 1) await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                            else ret = await this.RawExecuteIdentityAsync();
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        async protected Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit)
 | 
			
		||||
        {
 | 
			
		||||
            var ss = SplitSource(valuesLimit, parameterLimit);
 | 
			
		||||
@@ -140,35 +180,55 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteInsertedAsync", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    ret.AddRange(await this.RawExecuteInsertedAsync());
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        ret.AddRange(await this.RawExecuteInsertedAsync());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                ret.AddRange(await this.RawExecuteInsertedAsync());
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            ret.AddRange(await this.RawExecuteInsertedAsync());
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
@@ -178,7 +238,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        {
 | 
			
		||||
            var sql = ToSql();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var affrows = 0;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -193,7 +253,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return affrows;
 | 
			
		||||
        }
 | 
			
		||||
@@ -207,4 +267,3 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -299,7 +299,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            var sql = this.ToSql(field);
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            DataTable ret = null;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -314,7 +314,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
@@ -325,7 +325,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            var type = typeof(TTuple);
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var ret = new List<TTuple>();
 | 
			
		||||
            var flagStr = $"ToListField:{field}";
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
@@ -345,7 +345,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
@@ -353,7 +353,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        {
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var ret = new List<T1>();
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -377,7 +377,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            foreach (var include in _includeToList) include?.Invoke(ret);
 | 
			
		||||
            _trackToList?.Invoke(ret);
 | 
			
		||||
@@ -403,7 +403,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        {
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var ret = new List<T1>();
 | 
			
		||||
            var retCount = 0;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
@@ -444,7 +444,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, retCount);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            if (ret.Any() || checkDoneTimes == 0)
 | 
			
		||||
            {
 | 
			
		||||
@@ -492,7 +492,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            var type = typeof(TReturn);
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var ret = new List<TReturn>();
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -514,7 +514,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            if (typeof(TReturn) == typeof(T1))
 | 
			
		||||
                foreach (var include in _includeToList) include?.Invoke(ret);
 | 
			
		||||
@@ -1082,7 +1082,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            var sql = this.InternalToSql<int>(select);
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            DataTable ret = null;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -1097,7 +1097,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1142,7 +1142,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            var sql = this.ToSql(field);
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            DataTable ret = null;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -1157,7 +1157,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1168,7 +1168,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            var type = typeof(TTuple);
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var ret = new List<TTuple>();
 | 
			
		||||
            var flagStr = $"ToListField:{field}";
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
@@ -1189,7 +1189,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1198,7 +1198,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        {
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var ret = new List<T1>();
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -1223,7 +1223,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            foreach (var include in _includeToListAsync) await include?.Invoke(ret);
 | 
			
		||||
            _trackToList?.Invoke(ret);
 | 
			
		||||
@@ -1265,7 +1265,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            var type = typeof(TReturn);
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var ret = new List<TReturn>();
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -1288,7 +1288,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            if (typeof(TReturn) == typeof(T1))
 | 
			
		||||
                foreach (var include in _includeToListAsync) await include?.Invoke(ret);
 | 
			
		||||
@@ -1328,7 +1328,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            var sql = this.InternalToSql<int>(select);
 | 
			
		||||
            var dbParms = _params.ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            DataTable ret = null;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -1343,7 +1343,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -150,35 +150,55 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteAffrows", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    ret += this.RawExecuteAffrows();
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        ret += this.RawExecuteAffrows();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                ret += this.RawExecuteAffrows();
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            ret += this.RawExecuteAffrows();
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
@@ -197,35 +217,55 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteUpdated", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    ret.AddRange(this.RawExecuteUpdated());
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        ret.AddRange(this.RawExecuteUpdated());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                ret.AddRange(this.RawExecuteUpdated());
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = _orm.Ado.MasterPool.Get())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            ret.AddRange(this.RawExecuteUpdated());
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
@@ -238,7 +278,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (string.IsNullOrEmpty(sql)) return 0;
 | 
			
		||||
            var dbParms = _params.Concat(_paramsSource).ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var affrows = 0;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -254,7 +294,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return affrows;
 | 
			
		||||
        }
 | 
			
		||||
@@ -289,7 +329,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        public static void AuditDataValue(object sender, IEnumerable<T1> data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
 | 
			
		||||
        {
 | 
			
		||||
            if (data?.Any() != true) return;
 | 
			
		||||
            if (orm.Aop.AuditValue == null) return;
 | 
			
		||||
            if (orm.Aop.AuditValueHandler == null) return;
 | 
			
		||||
            foreach (var d in data)
 | 
			
		||||
            {
 | 
			
		||||
                if (d == null) continue;
 | 
			
		||||
@@ -297,7 +337,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                {
 | 
			
		||||
                    object val = col.GetMapValue(d);
 | 
			
		||||
                    var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties[col.CsName], val);
 | 
			
		||||
                    orm.Aop.AuditValue(sender, auditArgs);
 | 
			
		||||
                    orm.Aop.AuditValueHandler(sender, auditArgs);
 | 
			
		||||
                    if (auditArgs.IsChanged)
 | 
			
		||||
                    {
 | 
			
		||||
                        col.SetMapValue(d, val = auditArgs.Value);
 | 
			
		||||
@@ -309,13 +349,13 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        }
 | 
			
		||||
        public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
 | 
			
		||||
        {
 | 
			
		||||
            if (orm.Aop.AuditValue == null) return;
 | 
			
		||||
            if (orm.Aop.AuditValueHandler == null) return;
 | 
			
		||||
            if (data == null) return;
 | 
			
		||||
            foreach (var col in table.Columns.Values)
 | 
			
		||||
            {
 | 
			
		||||
                object val = col.GetMapValue(data);
 | 
			
		||||
                var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties[col.CsName], val);
 | 
			
		||||
                orm.Aop.AuditValue(sender, auditArgs);
 | 
			
		||||
                orm.Aop.AuditValueHandler(sender, auditArgs);
 | 
			
		||||
                if (auditArgs.IsChanged)
 | 
			
		||||
                {
 | 
			
		||||
                    col.SetMapValue(data, val = auditArgs.Value);
 | 
			
		||||
@@ -605,7 +645,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            else if (_source.Count > 1)
 | 
			
		||||
            { //批量保存 Source
 | 
			
		||||
                if (_table.Primarys.Any() == false) return null;
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                var caseWhen = new StringBuilder();
 | 
			
		||||
                caseWhen.Append("CASE ");
 | 
			
		||||
                ToSqlCase(caseWhen, _table.Primarys);
 | 
			
		||||
@@ -698,4 +738,4 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            return sb.ToString();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,35 +30,55 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteAffrowsAsync", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    ret += await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        ret += await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                ret += await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            ret += await this.RawExecuteAffrowsAsync();
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
@@ -76,35 +96,55 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (_transaction == null)
 | 
			
		||||
                this.WithTransaction(_orm.Ado.TransactionCurrentThread);
 | 
			
		||||
 | 
			
		||||
            if (_transaction != null)
 | 
			
		||||
            var before = new Aop.TraceBeforeEventArgs("SplitExecuteUpdatedAsync", null);
 | 
			
		||||
            _orm.Aop.TraceBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                if (_transaction != null || _batchAutoTransaction == false)
 | 
			
		||||
                {
 | 
			
		||||
                    _source = ss[a];
 | 
			
		||||
                    ret.AddRange(await this.RawExecuteUpdatedAsync());
 | 
			
		||||
                    for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                    {
 | 
			
		||||
                        _source = ss[a];
 | 
			
		||||
                        ret.AddRange(await this.RawExecuteUpdatedAsync());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                        var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null);
 | 
			
		||||
                        _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore);
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                            {
 | 
			
		||||
                                _source = ss[a];
 | 
			
		||||
                                ret.AddRange(await this.RawExecuteUpdatedAsync());
 | 
			
		||||
                            }
 | 
			
		||||
                            _transaction.Commit();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null));
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _transaction.Rollback();
 | 
			
		||||
                            _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex));
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                using (var conn = await _orm.Ado.MasterPool.GetAsync())
 | 
			
		||||
                {
 | 
			
		||||
                    _transaction = conn.Value.BeginTransaction();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = 0; a < ss.Length; a++)
 | 
			
		||||
                        {
 | 
			
		||||
                            _source = ss[a];
 | 
			
		||||
                            ret.AddRange(await this.RawExecuteUpdatedAsync());
 | 
			
		||||
                        }
 | 
			
		||||
                        _transaction.Commit();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        _transaction.Rollback();
 | 
			
		||||
                        throw;
 | 
			
		||||
                    }
 | 
			
		||||
                    _transaction = null;
 | 
			
		||||
                }
 | 
			
		||||
                exception = ex;
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.TraceAfterEventArgs(before, null, exception);
 | 
			
		||||
                _orm.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            ClearData();
 | 
			
		||||
            return ret;
 | 
			
		||||
@@ -116,7 +156,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            if (string.IsNullOrEmpty(sql)) return 0;
 | 
			
		||||
            var dbParms = _params.Concat(_paramsSource).ToArray();
 | 
			
		||||
            var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms);
 | 
			
		||||
            _orm.Aop.CurdBefore?.Invoke(this, before);
 | 
			
		||||
            _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
 | 
			
		||||
            var affrows = 0;
 | 
			
		||||
            Exception exception = null;
 | 
			
		||||
            try
 | 
			
		||||
@@ -132,7 +172,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
 | 
			
		||||
                _orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
                _orm.Aop.CurdAfterHandler?.Invoke(this, after);
 | 
			
		||||
            }
 | 
			
		||||
            return affrows;
 | 
			
		||||
        }
 | 
			
		||||
@@ -142,4 +182,4 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
        public abstract Task<List<T1>> ExecuteUpdatedAsync();
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -100,10 +100,10 @@ namespace FreeSql.Internal
 | 
			
		||||
        public TableAttribute GetEntityTableAttribute(Type type)
 | 
			
		||||
        {
 | 
			
		||||
            TableAttribute attr = null;
 | 
			
		||||
            if (_orm.Aop.ConfigEntity != null)
 | 
			
		||||
            if (_orm.Aop.ConfigEntityHandler != null)
 | 
			
		||||
            {
 | 
			
		||||
                var aope = new Aop.ConfigEntityEventArgs(type);
 | 
			
		||||
                _orm.Aop.ConfigEntity(_orm, aope);
 | 
			
		||||
                _orm.Aop.ConfigEntityHandler(_orm, aope);
 | 
			
		||||
                attr = aope.ModifyResult;
 | 
			
		||||
            }
 | 
			
		||||
            if (attr == null) attr = new TableAttribute();
 | 
			
		||||
@@ -130,10 +130,10 @@ namespace FreeSql.Internal
 | 
			
		||||
        public ColumnAttribute GetEntityColumnAttribute(Type type, PropertyInfo proto)
 | 
			
		||||
        {
 | 
			
		||||
            ColumnAttribute attr = null;
 | 
			
		||||
            if (_orm.Aop.ConfigEntityProperty != null)
 | 
			
		||||
            if (_orm.Aop.ConfigEntityPropertyHandler != null)
 | 
			
		||||
            {
 | 
			
		||||
                var aope = new Aop.ConfigEntityPropertyEventArgs(type, proto);
 | 
			
		||||
                _orm.Aop.ConfigEntityProperty(_orm, aope);
 | 
			
		||||
                _orm.Aop.ConfigEntityPropertyHandler(_orm, aope);
 | 
			
		||||
                attr = aope.ModifyResult;
 | 
			
		||||
            }
 | 
			
		||||
            if (attr == null) attr = new ColumnAttribute();
 | 
			
		||||
@@ -219,10 +219,10 @@ namespace FreeSql.Internal
 | 
			
		||||
        public IndexAttribute[] GetEntityIndexAttribute(Type type)
 | 
			
		||||
        {
 | 
			
		||||
            var ret = new Dictionary<string, IndexAttribute>();
 | 
			
		||||
            if (_orm.Aop.ConfigEntity != null)
 | 
			
		||||
            if (_orm.Aop.ConfigEntityHandler != null)
 | 
			
		||||
            {
 | 
			
		||||
                var aope = new Aop.ConfigEntityEventArgs(type);
 | 
			
		||||
                _orm.Aop.ConfigEntity(_orm, aope);
 | 
			
		||||
                _orm.Aop.ConfigEntityHandler(_orm, aope);
 | 
			
		||||
                foreach (var idxattr in aope.ModifyIndexResult)
 | 
			
		||||
                    if (!string.IsNullOrEmpty(idxattr.Name) && !string.IsNullOrEmpty(idxattr.Fields))
 | 
			
		||||
                    {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user