using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace SqlSugar
{
///
/// ** description:ActiveX Data Objects
/// ** author:sunkaixuan
/// ** date:2017/1/2
/// ** email:610262374@qq.com
///
public abstract partial class AdoProvider : AdoAccessory, IAdo
{
#region Constructor
public AdoProvider()
{
this.IsEnableLogEvent = false;
this.CommandType = CommandType.Text;
this.IsClearParameters = true;
this.CommandTimeOut = 300;
}
#endregion
#region Properties
protected List OutputParameters { get; set; }
public virtual string SqlParameterKeyWord { get { return "@"; } }
public IDbTransaction Transaction { get; set; }
public virtual SqlSugarProvider Context { get; set; }
internal CommandType OldCommandType { get; set; }
internal bool OldClearParameters { get; set; }
public IDataParameterCollection DataReaderParameters { get; set; }
public TimeSpan SqlExecutionTime { get { return AfterTime - BeforeTime; } }
public StackTraceInfo SqlStackTrace { get { return UtilMethods.GetStackTrace(); } }
public bool IsDisableMasterSlaveSeparation { get; set; }
internal DateTime BeforeTime = DateTime.MinValue;
internal DateTime AfterTime = DateTime.MinValue;
public virtual IDbBind DbBind
{
get
{
if (base._DbBind == null)
{
IDbBind bind = InstanceFactory.GetDbBind(this.Context.CurrentConnectionConfig);
base._DbBind = bind;
bind.Context = this.Context;
}
return base._DbBind;
}
}
public virtual int CommandTimeOut { get; set; }
public virtual CommandType CommandType { get; set; }
public virtual bool IsEnableLogEvent { get; set; }
public virtual bool IsClearParameters { get; set; }
public virtual Action LogEventStarting => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuting;
public virtual Action LogEventCompleted => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuted;
public virtual Func> ProcessingEventStartingSQL => this.Context.CurrentConnectionConfig.AopEvents?.OnExecutingChangeSql;
protected virtual Func FormatSql { get; set; }
public virtual Action ErrorEvent => this.Context.CurrentConnectionConfig.AopEvents?.OnError;
public virtual Action DiffLogEvent => this.Context.CurrentConnectionConfig.AopEvents?.OnDiffLogEvent;
public virtual List SlaveConnections { get; set; }
public virtual IDbConnection MasterConnection { get; set; }
public virtual string MasterConnectionString { get; set; }
public virtual CancellationToken? CancellationToken { get; set; }
#endregion
#region Connection
public virtual bool IsValidConnection()
{
try
{
using (OpenAlways())
{
return true;
}
}
catch (Exception)
{
return false;
}
}
public virtual bool IsValidConnectionNoClose()
{
try
{
this.Open();
return true;
}
catch (Exception)
{
return false;
}
}
public virtual void Open()
{
CheckConnection();
}
public SugarConnection OpenAlways()
{
SugarConnection result = new SugarConnection();
result.IsAutoClose = this.Context.CurrentConnectionConfig.IsAutoCloseConnection;
result.conn = this.Connection;
result.Context = this.Context;
this.Context.CurrentConnectionConfig.IsAutoCloseConnection = false;
this.Open();
return result;
}
public virtual void Close()
{
if (this.Transaction != null)
{
this.Transaction = null;
}
if (this.Connection != null && this.Connection.State == ConnectionState.Open)
{
this.Connection.Close();
}
if (this.IsMasterSlaveSeparation && this.SlaveConnections.HasValue())
{
foreach (var slaveConnection in this.SlaveConnections)
{
if (slaveConnection != null && slaveConnection.State == ConnectionState.Open)
{
slaveConnection.Close();
}
}
}
}
public virtual void Dispose()
{
if (this.Transaction != null)
{
this.Transaction.Rollback();
this.Transaction = null;
}
//if (this.Connection != null && this.Connection.State != ConnectionState.Open)
//{
// this.Connection.Close();
//}
if (this.Connection != null)
{
this.Connection.Dispose();
}
this.Connection = null;
if (this.IsMasterSlaveSeparation)
{
if (this.SlaveConnections != null)
{
foreach (var slaveConnection in this.SlaveConnections)
{
if (slaveConnection != null && slaveConnection.State == ConnectionState.Open)
{
slaveConnection.Dispose();
}
}
}
}
}
public virtual void CheckConnection()
{
if (this.Connection.State != ConnectionState.Open)
{
try
{
this.Connection.Open();
}
catch (Exception ex)
{
Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message+$"DbType=\"{this.Context.CurrentConnectionConfig.DbType}\";ConfigId=\"{this.Context.CurrentConnectionConfig.ConfigId}\"");
}
}
}
public virtual async Task CheckConnectionAsync()
{
if (this.Connection.State != ConnectionState.Open)
{
try
{
await (this.Connection as DbConnection).OpenAsync();
}
catch (Exception ex)
{
Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message + $"DbType=\"{this.Context.CurrentConnectionConfig.DbType}\";ConfigId=\"{this.Context.CurrentConnectionConfig.ConfigId}\"");
}
}
}
#endregion
#region Transaction
public virtual bool IsAnyTran()
{
return this.Transaction != null;
}
public virtual bool IsNoTran()
{
return this.Transaction == null;
}
public virtual void BeginTran()
{
CheckConnection();
if (this.Transaction == null)
this.Transaction = this.Connection.BeginTransaction();
}
public virtual async Task BeginTranAsync()
{
await CheckConnectionAsync();
if (this.Transaction == null)
this.Transaction =await (this.Connection as DbConnection).BeginTransactionAsync();
}
public virtual void BeginTran(IsolationLevel iso)
{
CheckConnection();
if (this.Transaction == null)
this.Transaction = this.Connection.BeginTransaction(iso);
}
public virtual async Task BeginTranAsync(IsolationLevel iso)
{
await CheckConnectionAsync();
if (this.Transaction == null)
this.Transaction =await (this.Connection as DbConnection).BeginTransactionAsync(iso);
}
public virtual void RollbackTran()
{
if (this.Transaction != null)
{
this.Transaction.Rollback();
this.Transaction = null;
if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) this.Close();
}
}
public virtual async Task RollbackTranAsync()
{
if (this.Transaction != null)
{
await (this.Transaction as DbTransaction).RollbackAsync();
this.Transaction = null;
if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) await this.CloseAsync();
}
}
public virtual void CommitTran()
{
if (this.Transaction != null)
{
this.Transaction.Commit();
this.Transaction = null;
if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) this.Close();
}
}
public virtual async Task CommitTranAsync()
{
if (this.Transaction != null)
{
await (this.Transaction as DbTransaction).CommitAsync();
this.Transaction = null;
if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) await this.CloseAsync();
}
}
#endregion
#region abstract
public abstract IDataParameter[] ToIDbDataParameter(params SugarParameter[] pars);
public abstract void SetCommandToAdapter(IDataAdapter adapter, DbCommand command);
public abstract IDataAdapter GetAdapter();
public abstract DbCommand GetCommand(string sql, SugarParameter[] pars);
public abstract IDbConnection Connection { get; set; }
public abstract void BeginTran(string transactionName);//Only SqlServer
public abstract void BeginTran(IsolationLevel iso, string transactionName);//Only SqlServer
#endregion
#region Use
public DbResult UseTran(Action action, Action errorCallBack = null)
{
var result = new DbResult();
try
{
this.BeginTran();
if (action != null)
action();
this.CommitTran();
result.Data = result.IsSuccess = true;
}
catch (Exception ex)
{
result.ErrorException = ex;
result.ErrorMessage = ex.Message;
result.IsSuccess = false;
this.RollbackTran();
if (errorCallBack != null)
{
errorCallBack(ex);
}
}
return result;
}
public async Task> UseTranAsync(Func action, Action errorCallBack = null)
{
var result = new DbResult();
try
{
await this.BeginTranAsync();
if (action != null)
await action();
await this.CommitTranAsync();
result.Data = result.IsSuccess = true;
}
catch (Exception ex)
{
result.ErrorException = ex;
result.ErrorMessage = ex.Message;
result.IsSuccess = false;
await this.RollbackTranAsync();
if (errorCallBack != null)
{
errorCallBack(ex);
}
}
return result;
}
public DbResult UseTran(Func action, Action errorCallBack = null)
{
var result = new DbResult();
try
{
this.BeginTran();
if (action != null)
result.Data = action();
this.CommitTran();
result.IsSuccess = true;
}
catch (Exception ex)
{
result.ErrorException = ex;
result.ErrorMessage = ex.Message;
result.IsSuccess = false;
this.RollbackTran();
if (errorCallBack != null)
{
errorCallBack(ex);
}
}
return result;
}
public async Task> UseTranAsync(Func> action, Action errorCallBack = null)
{
var result = new DbResult();
try
{
this.BeginTran();
if (action != null)
result.Data = await action();
this.CommitTran();
result.IsSuccess = true;
}
catch (Exception ex)
{
result.ErrorException = ex;
result.ErrorMessage = ex.Message;
result.IsSuccess = false;
this.RollbackTran();
if (errorCallBack != null)
{
errorCallBack(ex);
}
}
return result;
}
public IAdo UseStoredProcedure()
{
this.OldCommandType = this.CommandType;
this.OldClearParameters = this.IsClearParameters;
this.CommandType = CommandType.StoredProcedure;
this.IsClearParameters = false;
return this;
}
#endregion
#region Core
public virtual int ExecuteCommandWithGo(string sql, params SugarParameter[] parameters)
{
if (string.IsNullOrEmpty(sql))
return 0;
if (!sql.ToLower().Contains("go"))
{
return ExecuteCommand(sql);
}
System.Collections.ArrayList al = new System.Collections.ArrayList();
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(@"^(\s*)go(\s*)$", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.ExplicitCapture);
al.AddRange(reg.Split(sql));
int count = 0;
foreach (string item in al)
{
if (item.HasValue())
{
count += ExecuteCommand(item, parameters);
}
}
return count;
}
public virtual int ExecuteCommand(string sql, params SugarParameter[] parameters)
{
try
{
InitParameters(ref sql, parameters);
if (IsFormat(parameters))
sql = FormatSql(sql);
if (this.Context.CurrentConnectionConfig?.SqlMiddle?.IsSqlMiddle == true)
return this.Context.CurrentConnectionConfig.SqlMiddle.ExecuteCommand(sql, parameters);
SetConnectionStart(sql);
if (this.ProcessingEventStartingSQL != null)
ExecuteProcessingSQL(ref sql, ref parameters);
ExecuteBefore(sql, parameters);
IDbCommand sqlCommand = GetCommand(sql, parameters);
int count = sqlCommand.ExecuteNonQuery();
if (this.IsClearParameters)
sqlCommand.Parameters.Clear();
ExecuteAfter(sql, parameters);
sqlCommand.Dispose();
return count;
}
catch (Exception ex)
{
SugarCatch(ex, sql,parameters);
CommandType = CommandType.Text;
if (ErrorEvent != null)
ExecuteErrorEvent(sql, parameters, ex);
throw ex;
}
finally
{
if (this.IsAutoClose()) this.Close();
SetConnectionEnd(sql);
}
}
public virtual IDataReader GetDataReader(string sql, params SugarParameter[] parameters)
{
try
{
InitParameters(ref sql, parameters);
if (IsFormat(parameters))
sql = FormatSql(sql);
if (this.Context.CurrentConnectionConfig?.SqlMiddle?.IsSqlMiddle == true)
return this.Context.CurrentConnectionConfig.SqlMiddle.GetDataReader(sql, parameters);
SetConnectionStart(sql);
var isSp = this.CommandType == CommandType.StoredProcedure;
if (this.ProcessingEventStartingSQL != null)
ExecuteProcessingSQL(ref sql,ref parameters);
ExecuteBefore(sql, parameters);
IDbCommand sqlCommand = GetCommand(sql, parameters);
IDataReader sqlDataReader = sqlCommand.ExecuteReader(this.IsAutoClose() ? CommandBehavior.CloseConnection : CommandBehavior.Default);
if (isSp)
DataReaderParameters = sqlCommand.Parameters;
if (this.IsClearParameters)
sqlCommand.Parameters.Clear();
ExecuteAfter(sql, parameters);
SetConnectionEnd(sql);
if (SugarCompatible.IsFramework || this.Context.CurrentConnectionConfig.DbType != DbType.Sqlite)
sqlCommand.Dispose();
return sqlDataReader;
}
catch (Exception ex)
{
SugarCatch(ex, sql, parameters);
CommandType = CommandType.Text;
if (ErrorEvent != null)
ExecuteErrorEvent(sql, parameters, ex);
throw;
}
}
public virtual DataSet GetDataSetAll(string sql, params SugarParameter[] parameters)
{
try
{
InitParameters(ref sql, parameters);
if (IsFormat(parameters))
sql = FormatSql(sql);
if (this.Context.CurrentConnectionConfig?.SqlMiddle?.IsSqlMiddle == true)
return this.Context.CurrentConnectionConfig.SqlMiddle.GetDataSetAll(sql, parameters);
SetConnectionStart(sql);
if (this.ProcessingEventStartingSQL != null)
ExecuteProcessingSQL(ref sql,ref parameters);
ExecuteBefore(sql, parameters);
IDataAdapter dataAdapter = this.GetAdapter();
DbCommand sqlCommand = GetCommand(sql, parameters);
this.SetCommandToAdapter(dataAdapter, sqlCommand);
DataSet ds = new DataSet();
dataAdapter.Fill(ds);
if (this.IsClearParameters)
sqlCommand.Parameters.Clear();
ExecuteAfter(sql, parameters);
sqlCommand.Dispose();
return ds;
}
catch (Exception ex)
{
SugarCatch(ex, sql, parameters);
CommandType = CommandType.Text;
if (ErrorEvent != null)
ExecuteErrorEvent(sql, parameters, ex);
throw;
}
finally
{
if (this.IsAutoClose()) this.Close();
SetConnectionEnd(sql);
}
}
public virtual object GetScalar(string sql, params SugarParameter[] parameters)
{
try
{
InitParameters(ref sql, parameters);
if (IsFormat(parameters))
sql = FormatSql(sql);
if (this.Context.CurrentConnectionConfig?.SqlMiddle?.IsSqlMiddle == true)
return this.Context.CurrentConnectionConfig.SqlMiddle.GetScalar(sql, parameters);
SetConnectionStart(sql);
if (this.ProcessingEventStartingSQL != null)
ExecuteProcessingSQL(ref sql,ref parameters);
ExecuteBefore(sql, parameters);
IDbCommand sqlCommand = GetCommand(sql, parameters);
object scalar = sqlCommand.ExecuteScalar();
//scalar = (scalar == null ? 0 : scalar);
if (this.IsClearParameters)
sqlCommand.Parameters.Clear();
ExecuteAfter(sql, parameters);
sqlCommand.Dispose();
return scalar;
}
catch (Exception ex)
{
SugarCatch(ex, sql, parameters);
CommandType = CommandType.Text;
if (ErrorEvent != null)
ExecuteErrorEvent(sql, parameters, ex);
throw;
}
finally
{
if (this.IsAutoClose()) this.Close();
SetConnectionEnd(sql);
}
}
public virtual async Task ExecuteCommandAsync(string sql, params SugarParameter[] parameters)
{
try
{
Async();
InitParameters(ref sql, parameters);
if (IsFormat(parameters))
sql = FormatSql(sql);
if (this.Context.CurrentConnectionConfig?.SqlMiddle?.IsSqlMiddle == true)
return await this.Context.CurrentConnectionConfig.SqlMiddle.ExecuteCommandAsync(sql, parameters);
SetConnectionStart(sql);
if (this.ProcessingEventStartingSQL != null)
ExecuteProcessingSQL(ref sql,ref parameters);
ExecuteBefore(sql, parameters);
var sqlCommand = GetCommand(sql, parameters);
int count;
if (this.CancellationToken == null)
count=await sqlCommand.ExecuteNonQueryAsync();
else
count=await sqlCommand.ExecuteNonQueryAsync(this.CancellationToken.Value);
if (this.IsClearParameters)
sqlCommand.Parameters.Clear();
ExecuteAfter(sql, parameters);
sqlCommand.Dispose();
return count;
}
catch (Exception ex)
{
SugarCatch(ex, sql, parameters);
CommandType = CommandType.Text;
if (ErrorEvent != null)
ExecuteErrorEvent(sql, parameters, ex);
throw;
}
finally
{
if (this.IsAutoClose()) this.Close();
SetConnectionEnd(sql);
}
}
public virtual async Task GetDataReaderAsync(string sql, params SugarParameter[] parameters)
{
try
{
Async();
InitParameters(ref sql, parameters);
if (IsFormat(parameters))
sql = FormatSql(sql);
if (this.Context.CurrentConnectionConfig?.SqlMiddle?.IsSqlMiddle == true)
return await this.Context.CurrentConnectionConfig.SqlMiddle.GetDataReaderAsync(sql, parameters);
SetConnectionStart(sql);
var isSp = this.CommandType == CommandType.StoredProcedure;
if (this.ProcessingEventStartingSQL != null)
ExecuteProcessingSQL(ref sql,ref parameters);
ExecuteBefore(sql, parameters);
var sqlCommand = GetCommand(sql, parameters);
DbDataReader sqlDataReader;
if(this.CancellationToken==null)
sqlDataReader=await sqlCommand.ExecuteReaderAsync(this.IsAutoClose() ? CommandBehavior.CloseConnection : CommandBehavior.Default);
else
sqlDataReader=await sqlCommand.ExecuteReaderAsync(this.IsAutoClose() ? CommandBehavior.CloseConnection : CommandBehavior.Default,this.CancellationToken.Value);
if (isSp)
DataReaderParameters = sqlCommand.Parameters;
if (this.IsClearParameters)
sqlCommand.Parameters.Clear();
ExecuteAfter(sql, parameters);
SetConnectionEnd(sql);
if (SugarCompatible.IsFramework || this.Context.CurrentConnectionConfig.DbType != DbType.Sqlite)
sqlCommand.Dispose();
return sqlDataReader;
}
catch (Exception ex)
{
SugarCatch(ex, sql, parameters);
CommandType = CommandType.Text;
if (ErrorEvent != null)
ExecuteErrorEvent(sql, parameters, ex);
throw;
}
}
public virtual async Task