using MJTop.Data.SPI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Data;
using System.Data.Common;
using System.Collections.Specialized;
using MJTop.Data.DatabaseInfo;
using System.Reflection;
using System.Threading;
using System.Text.RegularExpressions;
using System.Collections.Concurrent;
namespace MJTop.Data
{
public partial class DB : IDB
{
///
/// 数据提供程序工厂
///
internal DbProviderFactory DBFactory
{
get;
set;
}
///
/// 连接字符串基类对象
///
public DbConnectionStringBuilder ConnectionStringBuilder { get; protected set; }
///
/// 数据库类型
///
public DBType DBType
{
get; protected set;
}
///
/// 数据库表列相关信息
///
public IDBInfo Info
{
get;
protected set;
}
///
/// 超时时间
///
internal int CmdTimeout
{
get;
set;
}
///
/// 连接字符串
///
internal string ConnectionString { get; set; }
#region AOP
///
/// 执行前
///
public Action OnExecuting { get; set; }
///
/// 执行后,附带返回值
///
public Action OnExecuted { get; set; }
///
/// 报异常时
///
public Action OnError { get; set; }
#endregion
///
/// 对数据 增删改 时触发
///
public TableTrigger DataChangeTriggers
{
get;
internal set;
}
#region 插入或更新排除列 设置与获取
///
/// 设置 插入时 要排除表列 集合
///
public ExcludeColumn InsertExcludeColumns
{
get;
internal set;
}
///
/// 获取 插入时 排除表列 集合
///
///
public NameValueCollection GetInsertExcludeColumns()
{
return InsertExcludeColumns.Coll;
}
///
/// 设置 更新时 要排除表列 集合
///
public ExcludeColumn UpdateExcludeColumns
{
get;
internal set;
}
///
/// 获取 更新时 排除表列 集合
///
///
public NameValueCollection GetUpdateExcludeColumns()
{
return InsertExcludeColumns.Coll;
}
public string ParameterChar
{
get
{
return DBType.ParameterChar();
}
}
#endregion
internal string ParameterSql(string parameterName)
{
if (DBType == DBType.OracleDDTek)
{
return "?";
}
return ParameterChar + parameterName;
}
///
/// 构建 参数化 对象
/// 不同数据库 参数化 时所使用的字符:Global.ParameterCharMap
///
/// 参数化 变量名
/// 参数化 值
/// 列信息
///
public DbParameter CreateParameter(string parameterName, object value, ColumnInfo colInfo = null)
{
DbParameter dbparameter = DBFactory.CreateParameter();
dbparameter.ParameterName = DBType.ParameterChar() + parameterName;
dbparameter.Value = value;
if (value == null || value == DBNull.Value)
{
dbparameter.Value = DBNull.Value;
}
else
{
DbType dbType;
if (colInfo != null)
{
dbType = colInfo.DbType;
object val = null;
val = Global.Dict_Convert_Type[dbType].Invoke(dbparameter.Value);
if (val is Exception)
{
throw val as Exception;
}
dbparameter.Value = val;
dbparameter.DbType = dbType;
}
else
{
Type tyValue = dbparameter.Value.GetType();
if (Global.TypeMap.TryGetValue(tyValue, out dbType))
{
dbparameter.DbType = dbType;
}
else
{
dbparameter.DbType = DbType.AnsiString;
}
}
}
return dbparameter;
}
///
/// 构建 参数化 对象
///
/// 参数化 变量名
/// 参数化 值
/// 数据类型
/// 参数化的方式
///
public DbParameter CreateParameter(string parameterName, object value, DbType type, ParameterDirection direction = ParameterDirection.Input)
{
DbParameter dbparameter = DBFactory.CreateParameter();
dbparameter.ParameterName = DBType.ParameterChar() + parameterName;
dbparameter.Value = value;
dbparameter.DbType = type;
dbparameter.Direction = direction;
return dbparameter;
}
///
/// 创建 Connection 对象
///
///
public DbConnection CreateConn()
{
return CreateConn(this.ConnectionString);
}
#region internal ado.net的四大核心对象
internal DbConnection CreateConn(string connectionString)
{
DbConnection _DBConn = DBFactory.CreateConnection();
if (!string.IsNullOrWhiteSpace(connectionString))
{
_DBConn.ConnectionString = connectionString;
}
return _DBConn;
}
internal DbCommand CreateCmd()
{
DbCommand _DBCmd = DBFactory.CreateCommand();
return _DBCmd;
}
internal DbCommand CreateCmd(string commandText = null, DbConnection DbConn = null)
{
DbCommand _DBCmd = DBFactory.CreateCommand();
if (DbConn != null)
{
_DBCmd.Connection = DbConn;
}
if (!string.IsNullOrWhiteSpace(commandText))
{
_DBCmd.CommandText = commandText;
}
return _DBCmd;
}
internal DbDataAdapter CreateAdapter(DbCommand dbCmd = null)
{
DbDataAdapter dbadapter = DBFactory.CreateDataAdapter();
if (dbCmd != null)
{
dbadapter.SelectCommand = dbCmd;
}
return dbadapter;
}
internal DbParameter CreateParameter()
{
DbParameter dbparameter = DBFactory.CreateParameter();
return dbparameter;
}
public void CheckTabStuct(string tableName, params string[] columnNames)
{
if (string.IsNullOrWhiteSpace(tableName))
{
throw new ArgumentNullException("tableName", "不能为空!");
}
if (!Info.TableNames.Contains(tableName, StringComparer.OrdinalIgnoreCase))
{
throw new ArgumentException(string.Format("不存在该表!{0}", "[" + tableName + "]"), "tableName:" + tableName);
}
if (columnNames != null && columnNames.Length > 0)
{
List lstAllColName = Info[tableName];
foreach (string columnName in columnNames)
{
if (!lstAllColName.Contains(columnName, StringComparer.OrdinalIgnoreCase))
{
throw new ArgumentException(string.Format("不存在该列!{0}", "[" + tableName + "." + columnName + "]"), "columnName:" + columnName, null);
}
}
}
}
#endregion
public DB(DBType dbType, DbProviderFactory dbFactory, string connectionString)
{
this.DBType = dbType;
this.DBFactory = dbFactory;
this.ConnectionString = connectionString;
this.ConnectionStringBuilder = DBFactory.CreateConnectionStringBuilder();
this.ConnectionStringBuilder.ConnectionString = connectionString;
this.InsertExcludeColumns = new ExcludeColumn(this);
this.UpdateExcludeColumns = new ExcludeColumn(this);
this.DataChangeTriggers = new TableTrigger(this);
{//查询数据库表列信息前,先验证数据库能否可以连接成功!
try
{
using (DbConnection conn = CreateConn())
{
conn.Open();
}
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(null, ex);
throw ex;
}
}
}
internal DbCommand BuildCommand(DbConnection conn, string cmdText, int timeOut = 30, CommandType cmdType = CommandType.Text)
{
return BuildCommandByParam(conn, cmdText, null, timeOut, cmdType);
}
static ConcurrentDictionary Dict_Type_Props = new ConcurrentDictionary();
internal DbCommand BuildCommandByParam(DbConnection conn, string cmdText, object cmdParms, int timeOut = 60, CommandType cmdType = CommandType.Text, string tableName = null)
{
if (conn.State != ConnectionState.Open)
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = cmdText;
cmd.CommandType = cmdType;
if (this.CmdTimeout != timeOut)
{
cmd.CommandTimeout = this.CmdTimeout;
}
else //以秒为单位)。默认为 30 秒
{
cmd.CommandTimeout = timeOut;
}
if (cmdParms != null)
{
if (cmdParms is DbParameter[])
{
DbParameter[] arr = cmdParms as DbParameter[];
cmd.Parameters.AddRange(arr);
}
else if (cmdParms is List)
{
List lstDp = cmdParms as List;
cmd.Parameters.AddRange(lstDp.ToArray());
}
else if (cmdParms is System.Collections.IDictionary)
{
IDictionary dict = cmdParms as IDictionary;
if (dict != null && dict.Count > 0)
{
foreach (DictionaryEntry kv in dict)
{
var parameter = cmd.CreateParameter();
parameter.ParameterName = ParameterChar + kv.Key.ToString();
parameter.Value = kv.Value;
if (parameter.Value == null || parameter.Value == DBNull.Value)
{
parameter.Value = DBNull.Value;
}
else
{
if (tableName != null)
{
ColumnInfo colInfo = Info[tableName, kv.Key.ToString()];
if (colInfo != null)
{
parameter.DbType = colInfo.DbType;
parameter.Value = Global.Dict_Convert_Type[colInfo.DbType].Invoke(parameter.Value);
}
}
else
{
Type tyValue = parameter.Value.GetType();
DbType tmpType;
if (Global.TypeMap.TryGetValue(tyValue, out tmpType))
{
parameter.DbType = tmpType;
}
else
{
parameter.DbType = DbType.AnsiString;
}
}
}
cmd.Parameters.Add(parameter);
}
}
}
else if (cmdParms is NameValueCollection)
{
NameValueCollection nvc = cmdParms as NameValueCollection;
if (nvc != null && nvc.Count > 0)
{
foreach (var key in nvc.AllKeys)
{
var parameter = cmd.CreateParameter();
parameter.ParameterName = ParameterChar + key;
parameter.Value = nvc[key];
if (parameter.Value == null || parameter.Value == DBNull.Value)
{
parameter.Value = DBNull.Value;
}
else
{
if (tableName != null)
{
ColumnInfo colInfo = Info[tableName, key];
if (colInfo != null)
{
parameter.DbType = colInfo.DbType;
parameter.Value = Global.Dict_Convert_Type[colInfo.DbType].Invoke(parameter.Value);
}
}
else
{
Type tyValue = parameter.Value.GetType();
DbType tmpType;
if (Global.TypeMap.TryGetValue(tyValue, out tmpType))
{
parameter.DbType = tmpType;
}
else
{
parameter.DbType = DbType.AnsiString;
}
}
}
cmd.Parameters.Add(parameter);
}
}
}
else
{
Type ty = cmdParms.GetType();
if (ty.Name.Contains("AnonymousType"))
{
PropertyInfo[] props;
if (!Dict_Type_Props.TryGetValue(ty, out props))
{
Dict_Type_Props[ty] = ty.GetProperties();
props = Dict_Type_Props[ty];
}
if (props != null && props.Length > 0)
{
foreach (var prop in props)
{
var parameter = cmd.CreateParameter();
parameter.ParameterName = ParameterChar + prop.Name;
parameter.Value = prop.GetValue(cmdParms, null);
if (parameter.Value == null || parameter.Value == DBNull.Value)
{
parameter.Value = DBNull.Value;
}
else
{
if (tableName != null)
{
ColumnInfo colInfo = Info[tableName, prop.Name];
if (colInfo != null)
{
parameter.DbType = colInfo.DbType;
parameter.Value = Global.Dict_Convert_Type[colInfo.DbType].Invoke(parameter.Value);
}
}
else
{
Type tyValue = parameter.Value.GetType();
DbType tmpType;
if (Global.TypeMap.TryGetValue(tyValue, out tmpType))
{
parameter.DbType = tmpType;
}
else
{
parameter.DbType = DbType.AnsiString;
}
}
}
cmd.Parameters.Add(parameter);
}
}
}
else
{
//其他类型
}
}
}
if (OnExecuting != null)
{
OnExecuting.Invoke(cmd);
}
return cmd;
}
///
/// 尝试 连接字符串 能否 连接成功
///
///
public virtual bool TryConnect()
{
try
{
using (DbConnection conn = CreateConn())
{
conn.Open();
}
return true;
}
catch
{
return false;
}
}
///
/// Sqlite3 收缩数据库(缓存数据写入到db文件中)
///
public void Shrink()
{
ExecSql("pragma journal_mode=delete;");
}
///
/// 验证 执行语句 是否 能执行通过
///
///
///
///
public virtual bool ValidateSql(string strSql, out Exception ex)
{
bool bResult = false;
ex = null;
DbConnection conn = null;
DbCommand cmd = null;
int res = -1;
try
{
conn = CreateConn();
strSql = "explain " + strSql;
cmd = BuildCommand(conn, strSql);
res = cmd.ExecuteNonQuery();
bResult = true;
}
catch (Exception e)
{
ex = e;
bResult = false;
}
finally
{
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, bResult);
}
return bResult;
}
public virtual int RunStoreProc(string storeProcName, object parameters = null)
{
DbConnection conn = null;
DbCommand cmd = null;
int cnt = -1;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, storeProcName, parameters, this.CmdTimeout, CommandType.StoredProcedure);
cnt = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, cnt);
}
return cnt;
}
public virtual DataTable RunStoreProcGetDT(string storeProcName, object parameters = null)
{
DataSet ds = new DataSet("ds");
DbConnection conn = null;
DbCommand cmd = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, storeProcName, parameters, this.CmdTimeout, CommandType.StoredProcedure);
DataAdapter adapter = CreateAdapter(cmd);
adapter.Fill(ds);
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
conn?.Close();
}
DataTable dt = null;
if (ds != null && ds.Tables.Count > 0)
{
dt = ds.Tables[0];
dt.TableName = "data";
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, dt);
}
return dt;
}
public virtual DataSet RunStoreProcGetDS(string storeProcName, object parameters = null)
{
DataSet ds = new DataSet("ds");
DbConnection conn = null;
DbCommand cmd = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, storeProcName, parameters, this.CmdTimeout, CommandType.StoredProcedure);
DataAdapter adapter = CreateAdapter(cmd);
adapter.Fill(ds);
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, ds);
}
return ds;
}
#region 基础查询
public virtual TRet Scalar(string strSql, TRet defRet, object parameters = null)
{
DbConnection conn = null;
DbCommand cmd = null;
object obj = null;
TRet result;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
obj = cmd.ExecuteScalar();
}
catch (Exception ex)
{
result = defRet;
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
}
finally
{
conn?.Close();
}
result = obj.ChangeType(default(TRet));
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, result);
}
return result;
}
public virtual NameValueCollection GetFirstRow(string strSql, object parameters = null)
{
DbConnection conn = null;
DbCommand cmd = null;
DbDataReader myReader = null;
NameValueCollection dict = new NameValueCollection();
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
myReader = cmd.ExecuteReader();
if (myReader.HasRows)
{
myReader.Read();
for (int j = 0; j < myReader.FieldCount; j++)
{
string columnName = myReader.GetName(j);
dict.Add(columnName, myReader[columnName] == null ? string.Empty : myReader[columnName].ToString());
}
}
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
myReader?.Close();
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, dict);
}
return dict;
}
public virtual DataTable GetDataTable(string strSql, object parameters = null)
{
DataSet ds = new DataSet("ds");
DbConnection conn = null;
DbCommand cmd = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
DataAdapter adapter = CreateAdapter(cmd);
adapter.Fill(ds);
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
conn?.Close();
}
DataTable dt = null;
if (ds != null && ds.Tables.Count > 0)
{
dt = ds.Tables[0];
dt.TableName = "data";
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, dt);
}
return dt;
}
public virtual List GetListTable(string strSql, object parameters = null)
{
List lstTabs = new List();
DataSet ds = new DataSet("ds");
DbConnection conn = null;
DbCommand cmd = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
DataAdapter adapter = CreateAdapter(cmd);
adapter.Fill(ds);
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
conn?.Close();
}
if (ds != null && ds.Tables.Count > 0)
{
foreach (DataTable tb in ds.Tables)
{
lstTabs.Add(tb);
}
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, lstTabs);
}
return lstTabs;
}
public virtual DataSet GetDataSet(string strSql, object parameters = null)
{
DataSet ds = new DataSet("ds");
DbConnection conn = null;
DbCommand cmd = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
DataAdapter adapter = CreateAdapter(cmd);
adapter.Fill(ds);
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
conn.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, ds);
}
return ds;
}
public virtual DbDataReader ExecReader(string commandText, object parameters = null, CommandType commandType = CommandType.Text)
{
DbConnection conn = null;
DbCommand cmd = null;
DbDataReader myReader = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, commandText, parameters, CmdTimeout, commandType);
myReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, myReader);
}
return myReader;
}
public virtual TRet Single(string strSql, TRet defRet, object parameters = null)
{
DbConnection conn = null;
DbCommand cmd = null;
DbDataReader myReader = null;
TRet result;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
myReader = cmd.ExecuteReader(CommandBehavior.SingleResult);
if (myReader.HasRows)
{
myReader.Read();
// ret = myReader.GetFieldValue(0);
result = myReader.GetValue(0).ChangeType(default(TRet));
}
else
{
result = defRet;
}
}
catch (Exception ex)
{
result = defRet;
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
}
finally
{
myReader?.Close();
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, result);
}
return result;
}
public virtual List> GetListDictionary(string strSql, object parameters = null)
{
DbConnection conn = null;
DbCommand cmd = null;
DbDataReader myReader = null;
List> lstDict = new List>();
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
myReader = cmd.ExecuteReader();
if (myReader.HasRows)
{
while (myReader.Read())
{
Dictionary dict = new Dictionary();
for (int j = 0; j < myReader.FieldCount; j++)
{
string columnName = myReader.GetName(j);
dict.Add(columnName, myReader[columnName]);
}
lstDict.Add(dict);
}
}
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
myReader?.Close();
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, lstDict);
}
return lstDict;
}
public virtual DataTable ReadTable(string strSql, object parameters = null)
{
DbConnection conn = null;
DbCommand cmd = null;
DbDataReader myReader = null;
DataTable data = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
myReader = cmd.ExecuteReader();
data = new DataTable("data");
if (myReader.HasRows)
{
bool isAddCol = false;
while (myReader.Read())
{
DataRow dr = data.NewRow();
for (int j = 0; j < myReader.FieldCount; j++)
{
string columnName = myReader.GetName(j);
if (!isAddCol)
{
data.Columns.Add(columnName, myReader.GetFieldType(j));
}
dr[columnName] = myReader[columnName];
}
data.Rows.Add(dr);
isAddCol = true;
}
}
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
myReader?.Close();
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, data);
}
return data;
}
public virtual List ReadList(string strSql, object parameters = null)
{
DbConnection conn = null;
DbCommand cmd = null;
DbDataReader myReader = null;
List lstVal = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
myReader = cmd.ExecuteReader();
lstVal = new List();
if (myReader.HasRows)
{
while (myReader.Read())
{
lstVal.Add(myReader.GetFieldValue(0));
}
}
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
myReader?.Close();
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, lstVal);
}
return lstVal;
}
public virtual NameValueCollection ReadNameValues(string strSql, object parameters = null)
{
DbConnection conn = null;
DbCommand cmd = null;
DbDataReader myReader = null;
NameValueCollection nvc = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
myReader = cmd.ExecuteReader();
nvc = new NameValueCollection();
if (myReader.HasRows)
{
while (myReader.Read())
{
nvc.Add((myReader.GetValue(0) ?? string.Empty).ToString(), (myReader.GetValue(1) ?? string.Empty).ToString());
}
}
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
myReader?.Close();
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, nvc);
}
return nvc;
}
public virtual Dictionary ReadDictionary(string strSql, object parameters = null, IEqualityComparer comparer = null)
{
DbConnection conn = null;
DbCommand cmd = null;
DbDataReader myReader = null;
Dictionary dict = null;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
myReader = cmd.ExecuteReader();
dict = new Dictionary(comparer);
if (myReader.HasRows)
{
while (myReader.Read())
{
dict.Add((TKey)myReader.GetValue(0).ChangeType(typeof(TKey)), (TValue)myReader.GetValue(1).ChangeType(typeof(TValue)));
}
}
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
myReader?.Close();
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, dict);
}
return dict;
}
#endregion
#region 执行
public virtual int ExecSql(string strSql, object parameters = null)
{
if (this.DBType == DBType.SQLite && !strSql.Contains("journal_mode=delete"))
{
return ExecSqlTran(strSql, parameters);
}
DbConnection conn = null;
DbCommand cmd = null;
int cnt = -1;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
cnt = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
throw ex;
}
finally
{
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, cnt);
}
return cnt;
}
public int ExecSqlTran(string strSql, object parameters = null)
{
DbConnection conn = null;
DbCommand cmd = null;
DbTransaction tran = null;
int cnt = -1;
try
{
conn = CreateConn();
cmd = BuildCommandByParam(conn, strSql, parameters);
tran = conn.BeginTransaction();
cmd.Transaction = tran;
cnt = cmd.ExecuteNonQuery();
tran.Commit();
}
catch (Exception ex)
{
tran?.Rollback();
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
}
finally
{
conn?.Close();
}
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, cnt);
}
return cnt;
}
public virtual int ExecSqlTran(params string[] sqlCmds)
{
if (sqlCmds == null || sqlCmds.Length == 0)
{
return -1;
}
DbConnection conn = null;
DbCommand cmd = null;
DbTransaction tran = null;
int cnt = 0;
try
{
conn = CreateConn();
conn.Open();
tran = conn.BeginTransaction();
cmd = conn.CreateCommand();
cmd.Transaction = tran;
cmd.CommandTimeout = this.CmdTimeout;
for (int n = 0; n < sqlCmds.Length; n++)
{
string strsql = sqlCmds[n];
if (strsql.Trim().Length > 1)
{
cmd.CommandText = strsql;
if (OnExecuting != null)
{
OnExecuting.Invoke(cmd);
}
int res = cmd.ExecuteNonQuery();
cnt += res;
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, res);
}
}
}
tran.Commit();
}
catch (Exception ex)
{
tran.Rollback();
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
}
finally
{
conn?.Close();
}
return cnt;
}
public virtual int ExecSqlTran(List>> strSqlList)
{
if (strSqlList == null || strSqlList.Count <= 0)
{
return -1;
}
DbConnection conn = null;
DbCommand cmd = null;
DbTransaction tran = null;
int cnt = 0;
try
{
conn = CreateConn();
conn.Open();
tran = conn.BeginTransaction();
cmd = conn.CreateCommand();
cmd.Transaction = tran;
cmd.CommandTimeout = this.CmdTimeout;
for (int n = 0; n < strSqlList.Count; n++)
{
var kv = strSqlList[n];
if (!string.IsNullOrWhiteSpace(kv.Key))
{
cmd.CommandText = kv.Key;
if (kv.Value != null && kv.Value.Count > 0)
{
cmd.Parameters.AddRange(kv.Value.ToArray());
}
if (OnExecuting != null)
{
OnExecuting.Invoke(cmd);
}
int res = cmd.ExecuteNonQuery();
cnt += res;
if (OnExecuted != null)
{
OnExecuted.Invoke(cmd, res);
}
}
}
tran.Commit();
}
catch (Exception ex)
{
tran.Rollback();
if (this.OnError != null)
this.OnError.Invoke(cmd, ex);
}
finally
{
conn?.Close();
}
return cnt;
}
#endregion
public virtual int BulkInsert(string tableName, DataTable data,int batchSize = 200000, int timeout = 60)
{
throw new NotImplementedException("该方法未支持!(" + this.DBType + ")");
}
public virtual int BulkInsert(string tableName, DbDataReader reader, int batchSize = 200000, int timeout = 60)
{
throw new NotImplementedException("该方法未支持!(" + this.DBType + ")");
}
public KeyValuePair> InsertScript(DT data, string tableName, params string[] excludeColNames)
{
if (data == null)
throw new ArgumentException("data", "不能为null!");
CheckTabStuct(tableName);
StringBuilder sb_beforeSQL = new StringBuilder();
sb_beforeSQL.Append("insert into " + tableName + " (");
StringBuilder sb_afterSQl = new StringBuilder();
sb_afterSQl.Append(") values (");
string insert_sql = string.Empty;
List lstPara = new List();
var lstColName = Info[tableName];
IEnumerable enumNames = new List();
if (TypeInfo.IsAnonymousType)
{
#region 匿名对象
var curNames = TypeInfo.PropNames;
enumNames = curNames.Intersect(lstColName, StringComparer.OrdinalIgnoreCase);
if (excludeColNames != null && excludeColNames.Length > 0)
{
enumNames = enumNames.Except(excludeColNames, StringComparer.OrdinalIgnoreCase);
}
string[] columnNames = InsertExcludeColumns.Coll.GetValues(tableName);
if (columnNames != null && columnNames.Length > 0)
{
enumNames = enumNames.Except(columnNames, StringComparer.OrdinalIgnoreCase);
}
foreach (var colName in enumNames)
{
ColumnInfo colInfo = Info[tableName, colName];
if (colInfo.IsIdentity)
{
continue;
}
object obj = TypeInfo.PropMapping[colName].GetValue(data, null);
if (!string.IsNullOrWhiteSpace(colInfo.DefaultVal)
&& (obj == null || string.IsNullOrEmpty(obj.ToString())))
{
continue;
}
DbParameter dp = CreateParameter(colName, obj, colInfo);
lstPara.Add(dp);
sb_beforeSQL.Append(colName + ",");
sb_afterSQl.Append(ParameterSql(colName) + ",");
}
#endregion
}
else if (TypeInfo.IsNameValueColl)
{
#region NameValueCollection
var curNames = (data as NameValueCollection).AllKeys;
enumNames = curNames.Intersect(lstColName, StringComparer.OrdinalIgnoreCase);
if (excludeColNames != null && excludeColNames.Length > 0)
{
enumNames = enumNames.Except(excludeColNames, StringComparer.OrdinalIgnoreCase);
}
foreach (var colName in enumNames)
{
ColumnInfo colInfo = Info[tableName, colName];
if (colInfo.IsIdentity)
{
continue;
}
object obj = (data as NameValueCollection)[colName];
if (!string.IsNullOrWhiteSpace(colInfo.DefaultVal)
&& (obj == null || string.IsNullOrEmpty(obj.ToString())))
{
continue;
}
DbParameter dp = CreateParameter(colName, obj, colInfo);
lstPara.Add(dp);
sb_beforeSQL.Append(colName + ",");
sb_afterSQl.Append(ParameterSql(colName) + ",");
}
#endregion
}
else if (TypeInfo.IsDict)
{
#region IDictionary
var curNames = (data as IDictionary).Keys;
string[] arrKeys = new string[curNames.Count];
curNames.CopyTo(arrKeys, 0);
enumNames = arrKeys.Intersect(lstColName, StringComparer.OrdinalIgnoreCase);
if (excludeColNames != null && excludeColNames.Length > 0)
{
enumNames = enumNames.Except(excludeColNames, StringComparer.OrdinalIgnoreCase);
}
foreach (var colName in enumNames)
{
ColumnInfo colInfo = Info[tableName, colName];
if (colInfo.IsIdentity)
{
continue;
}
object obj = (data as IDictionary)[colName];
if (!string.IsNullOrWhiteSpace(colInfo.DefaultVal)
&& (obj == null || string.IsNullOrEmpty(obj.ToString())))
{
continue;
}
DbParameter dp = CreateParameter(colName, obj, colInfo);
lstPara.Add(dp);
sb_beforeSQL.Append(colName + ",");
sb_afterSQl.Append(ParameterSql(colName) + ",");
}
#endregion
}
else
{
throw new ArgumentException("未知数据类型插入!", "data");
}
if (!enumNames.Any())
{
throw new ArgumentException("至少有1列的值,才能够插入!", "data");
}
insert_sql = sb_beforeSQL.ToString().TrimEnd(',') + sb_afterSQl.ToString().TrimEnd(',') + ")";
return new KeyValuePair>(insert_sql, lstPara);
}
public virtual bool Insert(DT data, string tableName, params string[] excludeColNames)
{
var kv = InsertScript(data, tableName, excludeColNames);
bool res = false;
res = ExecSql(kv.Key, kv.Value) > 0;
var lstAct = DataChangeTriggers.GetActions(tableName);
if (lstAct.Any())
{
foreach (var act in lstAct)
{
act.Invoke();
}
}
return res;
}
internal virtual Ret InsertGet(DT data, string tableName, params string[] excludeColNames)
{
var kv = InsertScript(data, tableName, excludeColNames);
string insert_Sql = kv.Key + ";" + Script.IdentitySql(DBType, tableName);
var res = Single(insert_Sql, default(Ret), kv.Value);
var lstAct = DataChangeTriggers.GetActions(tableName);
if (lstAct.Any())
{
foreach (var act in lstAct)
{
act.Invoke();
}
}
return res;
}
public virtual int InsertGetInt(DT data, string tableName, params string[] excludeColNames)
{
return InsertGet(data, tableName, excludeColNames);
}
public virtual long InsertGetLong(DT data, string tableName, params string[] excludeColNames)
{
return InsertGet(data, tableName, excludeColNames);
}
public KeyValuePair> UpdateScript(DT data, string tableName, string pkOrUniqueColName = "Id", params string[] excludeColNames)
{
if (data == null)
throw new ArgumentException("data", "不能为null!");
CheckTabStuct(tableName, pkOrUniqueColName);
string parameterChar = DBType.ParameterChar();
StringBuilder sb_beforeSQL = new StringBuilder();
sb_beforeSQL.Append("update " + tableName + " set ");
string update_sql = string.Empty;
DbParameter paraPKOrUnique = null;
string paraPKOrUniqueName = string.Empty;
List lstPara = new List();
var lstColName = Info[tableName];
IEnumerable enumNames = new List();
if (TypeInfo.IsAnonymousType)
{
#region 匿名对象
var curNames = TypeInfo.PropNames;
enumNames = curNames.Intersect(lstColName, StringComparer.OrdinalIgnoreCase);
if (excludeColNames != null && excludeColNames.Length > 0)
{
enumNames = enumNames.Except(excludeColNames, StringComparer.OrdinalIgnoreCase);
}
foreach (var colName in enumNames)
{
ColumnInfo colInfo = Info[tableName, colName];
object obj = TypeInfo.PropMapping[colName].GetValue(data, null);
if (!colName.Equals(pkOrUniqueColName, StringComparison.OrdinalIgnoreCase))
{
sb_beforeSQL.Append(colName + "=" + ParameterSql(colName) + ",");
DbParameter dp = CreateParameter(colName, obj, colInfo);
lstPara.Add(dp);
}
else
{
paraPKOrUnique = CreateParameter(colName, obj, colInfo);
paraPKOrUniqueName = colName;
}
}
#endregion
}
else if (TypeInfo.IsNameValueColl)
{
#region NameValueCollection
var curNames = (data as NameValueCollection).AllKeys;
enumNames = curNames.Intersect(lstColName, StringComparer.OrdinalIgnoreCase);
if (excludeColNames != null && excludeColNames.Length > 0)
{
enumNames = enumNames.Except(excludeColNames, StringComparer.OrdinalIgnoreCase);
}
foreach (var colName in enumNames)
{
ColumnInfo colInfo = Info[tableName, colName];
object obj = (data as NameValueCollection)[colName];
if (!colName.Equals(pkOrUniqueColName, StringComparison.OrdinalIgnoreCase))
{
sb_beforeSQL.Append(colName + "=" + ParameterSql(colName) + ",");
DbParameter dp = CreateParameter(colName, obj, colInfo);
lstPara.Add(dp);
}
else
{
paraPKOrUnique = CreateParameter(colName, obj, colInfo);
paraPKOrUniqueName = colName;
}
}
#endregion
}
else if (TypeInfo.IsDict)
{
#region IDictionary
var curNames = (data as IDictionary).Keys;
string[] arrKeys = new string[curNames.Count];
curNames.CopyTo(arrKeys, 0);
enumNames = arrKeys.Intersect(lstColName, StringComparer.OrdinalIgnoreCase);
if (excludeColNames != null && excludeColNames.Length > 0)
{
enumNames = enumNames.Except(excludeColNames, StringComparer.OrdinalIgnoreCase);
}
foreach (var colName in enumNames)
{
ColumnInfo colInfo = Info[tableName, colName];
object obj = (data as IDictionary)[colName];
if (!colName.Equals(pkOrUniqueColName, StringComparison.OrdinalIgnoreCase))
{
sb_beforeSQL.Append(colName + "=" + ParameterSql(colName) + ",");
DbParameter dp = CreateParameter(colName, obj, colInfo);
lstPara.Add(dp);
}
else
{
paraPKOrUnique = CreateParameter(colName, obj, colInfo);
paraPKOrUniqueName = colName;
}
}
#endregion
}
else
{
throw new ArgumentException("未知数据类型插入!", "data");
}
if (!enumNames.Any())
{
throw new ArgumentException("至少有1列的值才能够更新!", "data");
}
update_sql = sb_beforeSQL.ToString().TrimEnd(',') + (" where " + paraPKOrUniqueName + "=" + ParameterSql(pkOrUniqueColName));
lstPara.Add(paraPKOrUnique);
return new KeyValuePair>(update_sql, lstPara);
}
public virtual bool Update(DT data, string tableName, string pkOrUniqueColName = "Id", params string[] excludeColNames)
{
var kv = UpdateScript(data, tableName, pkOrUniqueColName, excludeColNames);
var res = ExecSql(kv.Key, kv.Value) > 0;
var lstAct = DataChangeTriggers.GetActions(tableName);
if (lstAct.Any())
{
foreach (var act in lstAct)
{
act.Invoke();
}
}
return res;
}
///
/// 保存策略:
/// 1.如果表没有设置主键,则进行的是插入操作
/// 2.如果表的主键是自增,如果data中主键有值,则进行更新操作,没有值则进行插入操作
/// 3.如果表有主键,不是自增,则从数据查询,存在则更新,不存在则插入。注:如果主键列的值为空,则报异常!
///
///
///
///
///
///
///
private KeyValuePair> SaveScript(DT data, string tableName, out SaveType saveType, string pkOrUniqueColName = "Id", params string[] excludeColNames)
{
saveType = SaveType.Insert;
if (data == null)
throw new ArgumentException("data", "不能为null!");
CheckTabStuct(tableName, pkOrUniqueColName);
var tableInfo = Info.TableInfoDict[tableName];
if (tableInfo.PriKeyType == PrimaryKeyType.UNKNOWN)
{
return InsertScript(data, tableName, pkOrUniqueColName);
}
else
{
object pkOrUniqueColValue = null;
if (TypeInfo.IsAnonymousType)
{
PropertyInfo pkOrUniqueColPy;
if (TypeInfo.PropMapping.TryGetValue(pkOrUniqueColName, out pkOrUniqueColPy))
{
pkOrUniqueColValue = pkOrUniqueColPy.GetValue(data, null);
}
}
else if (TypeInfo.IsNameValueColl)
{
var nvc = (data as NameValueCollection);
pkOrUniqueColValue = nvc[pkOrUniqueColName];
}
else if (TypeInfo.IsDict)
{
var dict = (data as IDictionary);
dict.TryGetValue(pkOrUniqueColName, out pkOrUniqueColValue);
}
else
{
throw new ArgumentException("未知数据类型插入!", "data");
}
if (tableInfo.PriKeyType == PrimaryKeyType.AUTO)
{
if (pkOrUniqueColValue == null || string.IsNullOrWhiteSpace(pkOrUniqueColValue.ToString()))
{
saveType = SaveType.Insert;
return InsertScript(data, tableName, pkOrUniqueColName);
}
else
{
saveType = SaveType.Update;
return UpdateScript(data, tableName, pkOrUniqueColName, excludeColNames);
}
}
else//PrimaryKeyType.SET
{
if (pkOrUniqueColValue == null || string.IsNullOrWhiteSpace(pkOrUniqueColValue.ToString()))
{
throw new ArgumentException("主键列的值不能为空![" + pkOrUniqueColName + "]");
}
if (!Exist(tableName, pkOrUniqueColName, pkOrUniqueColValue, null))
{
saveType = SaveType.Insert;
//return InsertScript(data, tableName, pkOrUniqueColName);
return InsertScript(data, tableName);
}
else
{
saveType = SaveType.Update;
return UpdateScript(data, tableName, pkOrUniqueColName, excludeColNames);
}
}
}
}
///
/// 保存策略:
/// 1.如果表没有设置主键,则进行的是插入操作
/// 2.如果表的主键是自增,如果data中主键有值,则进行更新操作,没有值则进行插入操作
/// 3.如果表有主键,不是自增,则从数据查询,存在则更新,不存在则插入。注:如果主键列的值为空,则报异常!
///
///
///
///
///
///
///
public virtual KeyValuePair Save(DT data, string tableName, string pkOrUniqueColName = "Id", params string[] excludeColNames)
{
SaveType saveType;
var kv = SaveScript(data, tableName, out saveType, pkOrUniqueColName, excludeColNames);
bool res = ExecSql(kv.Key, kv.Value) > 0;
var lstAct = DataChangeTriggers.GetActions(tableName);
if (lstAct.Any())
{
foreach (var act in lstAct)
{
act.Invoke();
}
}
return new KeyValuePair(saveType, res);
}
public virtual KeyValuePair GetDataTableByPager(int currentPage, int pageSize, string selColumns, string joinTableName, string whereStr, string orderbyStr)
{
long totalCount;
DataTable data = GetDataTableByPager(currentPage, pageSize, selColumns, joinTableName, whereStr, orderbyStr, out totalCount);
return new KeyValuePair(data, totalCount);
}
protected virtual DataTable GetDataTableByPager(int currentPage, int pageSize, string selColumns, string joinTableName, string whereStr, string orderbyStr, out long totalCount)
{
throw new NotImplementedException(DBType + "暂未支持");
}
public virtual bool DeleteAll(string tableName)
{
string strSql = "delete from " + ParameterSql(tableName);
ExecSql(strSql, CreateParameter(tableName, tableName).TransArray());
return true;
}
}
}