/////////////////////////////////////////////////////////////////////////////
// File Description : DAL中的所有数据访问类,都需要继承BaseDAL
// Copyright : joyin
// -------------------------------------------------------------------------
// Date Created : Mar 26, 2010
// Author : jiangxinjun
// -------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////
#region Namespace
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Reflection;
using HanHe.Utility;
using HanHe.Utility.Data;
using HH.WMS.Entitys.Common;
using HH.WMS.Common;
using HH.Redis.ReisModel;
using HH.WMS.Entitys.Basic;
#endregion
namespace HH.WMS.DAL
{
///
/// 创建Database委托
///
/// 数据访问工具类实例
//public delegate Database CreateDataBaseHandler();
///
/// DAL所有数据访问类的基类
///
/// DAL中的所有数据访问类,都需要继承BaseDAL
public class ErpBaseDAL : BaseDataUtility
{
public RedisUserEntity userInfo;
public enum DBTYPE
{
MYSQL,
MSSQL,
ORACLE,
ORTHER
}
public DBTYPE NowDbType
{
get
{
if (Now_dbType.Equals("MYSQL"))
return DBTYPE.MYSQL;
if (Now_dbType.Equals("MSSQL"))
return DBTYPE.MSSQL;
if (Now_dbType.Equals("ORACLE"))
return DBTYPE.ORACLE;
return DBTYPE.ORTHER;
}
}
public string Now_dbType = "MSSQL";
///
/// 创建Database委托
///
/// 数据访问工具类实例
public delegate Database CreateDataBaseHandler();
#region 初始化
private Database db;
private string databaseName;
///
/// 默认的数据库连接字符串在配置文件的名称(根据连接配置获得所要连接的数据库)
///
internal static readonly string DATABASE_NAME = "erpConnection";
///
/// 默认根据属性名获取属性对象的策略。
///
private static BindingFlags PublicInstancePropertyBindingFlags = BindingFlags.CreateInstance
| BindingFlags.Instance //实例
| BindingFlags.Public //公有
| BindingFlags.SetProperty //可写属性
| BindingFlags.IgnoreCase; //忽略大小写
///
/// 构造函数
///
public ErpBaseDAL()
: this(DATABASE_NAME)
{
}
///
/// 构造函数
///
/// 数据库连接字符串在配置文件的名称
internal ErpBaseDAL(string databaseName)
{
this.databaseName = databaseName;
}
///
/// 创建Database对象
///
/// 数据访问工具类实例
protected override Database CreateDataBase()
{
if (db == null)
{
db = CreateDataAccess(databaseName);
}
return db;
}
///
/// 获取Database对象
///
private Database Database
{
get
{
return CreateDataBase();
}
}
#endregion
#region DataAccess
///
/// 数据库执行工具类
///
internal protected new Database DataAccess
{
get
{
return base.DataAccess;
}
}
#endregion
#region ExecuteInsertWithGetIdentity
///
/// 执行Insert语句,并且输出新增的自增长值
///
/// Sql命令
/// 事务对象,如果为null,则不使用事务
/// 如果执行Insert语句成功,则输出自增长值;否则输出0.
/// 执行结果,参考
/// 如果参数trans不为null的话:调用此方法的过程中,trans是不会做Commit,必须方法外部做Commit;但如果出现异常,trans会执行Rollback。
internal SqlExecuteResult ExecuteInsertWithGetIdentity(DbCommand cmd, DbTransaction trans, out int id)
{
SqlExecuteResult result = new SqlExecuteResult();
id = default(int);
//在Insert语句后面添加获取自增长Id的语句
cmd.CommandText += ";" + CommonUseSqlFormat.RETRIEVE_NEWID;
if (trans == null)
{
try
{
object newid = DataAccess.ExecuteScalar(cmd);
if (!IsNullValue(newid))
{
id = Convert.ToInt32(newid);
result.Success = true;
}
}
catch (Exception ex)
{
result.Success = false;
result.Exception = ex;
}
}
else
{
try
{
object newid = DataAccess.ExecuteScalar(cmd, trans);
if (!IsNullValue(newid))
{
id = Convert.ToInt32(newid);
result.Success = true;
}
}
catch (Exception ex)
{
result.Success = false;
result.Exception = ex;
DAOManager.RollbackTransaction(trans);
}
}
return result;
}
#endregion
#region ExecuteCommand
///
/// 在事务中,执行Sql命令。
///
/// Sql命令
/// 事务对象,如果为null,则不使用事务
/// 执行结果,参考
/// 如果参数trans不为null的话:调用此方法的过程中,trans是不会做Commit,必须方法外部做Commit;但如果出现异常,trans会执行Rollback。
internal SqlExecuteResult ExecuteCommand(DbCommand command, DbTransaction trans)
{
SqlExecuteResult result = new SqlExecuteResult();
if (trans == null)
{
//自己创建一个事务执行
return DAOManager.ExecuteTransaction(this.Database, _trans =>
{
try
{
result.Row = DataAccess.ExecuteNonQuery(command, _trans);
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.Exception = ex;
DAOManager.RollbackTransaction(_trans);
}
return result;
});
}
else
{
try
{
result.Row = DataAccess.ExecuteNonQuery(command, trans);
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.Exception = ex;
DAOManager.RollbackTransaction(trans);
}
}
return result;
}
#endregion
#region ExecuteCommands
///
/// 在事务中,执行一组Sql命令。
///
/// Sql命令列表
/// 事务对象,如果为null,则不使用事务
/// 执行结果,参考
/// 如果参数trans不为null的话:调用此方法的过程中,trans是不会做Commit,必须方法外部做Commit;但如果出现异常,trans会执行Rollback。
public SqlExecuteResult ExecuteCommands(List commands, DbTransaction trans)
{
SqlExecuteResult result = new SqlExecuteResult();
if (trans == null)
{
//自己创建一个事务执行
return DAOManager.ExecuteTransaction(this.Database, _trans =>
{
try
{
foreach (var command in commands)
{
DataAccess.ExecuteNonQuery(command, _trans);
}
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.Exception = ex;
DAOManager.RollbackTransaction(_trans);
}
return result;
});
}
else
{
try
{
foreach (var command in commands)
{
DataAccess.ExecuteNonQuery(command, trans);
}
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.Exception = ex;
DAOManager.RollbackTransaction(trans);
}
}
return result;
}
#endregion
#region CheckExit
///
///
///
/// 表名称
/// 栏位名
/// 比对的值
/// PK的栏位
///
/// 输出结果,参考。如果数据存在,SqlExecuteResult的TokenObject包含了此笔数据的Id值;Exception抛出的异常类型为CheckExistException
internal bool CheckExitObj(string tableName, string columnName, string mapperValue
, string idColumnName)
{
bool isExist = false;
/*
* 组合执行以下Sql
* select {idColumnName} from {tableName} where {columnName} = {mapperValue}
*/
string sql = string.Format("SELECT {2} FROM {0} WHERE {1} = @val "
, tableName, columnName, idColumnName);
DbCommand cmd = DataAccess.GetSqlStringCommand(sql);
DataAccess.AddInParameter(cmd, "val", DbType.String, mapperValue);
object _Obj = DataAccess.ExecuteScalar(cmd);
if (_Obj != null)
isExist = true;
return isExist;
}
#endregion
#region CheckExist
///
/// 检查数据是否在数据库中才能在
///
/// 表名称
/// 栏位名
/// 比对的值
/// PK的栏位
/// 事务
/// 输出结果,参考。如果数据存在,SqlExecuteResult的TokenObject包含了此笔数据的Id值;Exception抛出的异常类型为CheckExistException
/// true,表示数据已存在;false,相关数据不存在。
internal bool CheckExist(string tableName, string columnName, string mapperValue
, string idColumnName, DbTransaction trans
, out SqlExecuteResult result)
{
bool isExist = false;
result = null;
/*
* 组合执行以下Sql
* select {idColumnName} from {tableName} where {columnName} = {mapperValue}
*/
string sql = string.Format("SELECT {2} FROM {0} WHERE {1} = @val "
, tableName, columnName, idColumnName);
DbCommand cmd = DataAccess.GetSqlStringCommand(sql);
DataAccess.AddInParameter(cmd, "val", DbType.String, mapperValue);
using (IDataReader dr = (trans == null ? DataAccess.ExecuteReader(cmd) : DataAccess.ExecuteReader(cmd, trans)))
{
if (dr.Read())
{
isExist = true;
result = new SqlExecuteResult()
{
Success = false,
//检测记录是否存在的异常
Exception = new CheckExistException()
{
Mark = columnName.ToLower()
},
TokenObject = dr[idColumnName],
};
}
dr.Close();
}
// object obj = (trans == null ? DataAccess.ExecuteScalar(cmd) : DataAccess.ExecuteScalar(cmd, trans));
return isExist;
}
#endregion
#region SetCommandValue
#region CommandMapper
///
/// 字段名称映射
///
internal class CommandMapper
{
///
/// 构造函数
///
/// 字段名称(参数名与字段名一样、属性名为字段名去掉下划线)
internal CommandMapper(string colName)
: this(colName, colName, GetPropertyNameByColumnName(colName))
{
}
///
/// 构造函数
///
/// 字段名称
/// 参数名称
/// 属性名称
internal CommandMapper(string colName, string parameterName, string propertyName)
{
this.ColumnName = colName;
this.ParameterName = parameterName;
this.PropertyName = propertyName;
}
///
/// 字段名称
///
internal string ColumnName { get; private set; }
///
/// 参数名称
///
internal string ParameterName { get; private set; }
///
/// 属性名称
///
internal string PropertyName { get; private set; }
}
#endregion
#region SetCommandValueWithCheck
///
/// 为DbCommand赋值参数,赋值时添加检测(只检测字符串大小是否大于数据库所设长度)
///
/// 实体
/// 字段、属性、参数名称的映射关系
/// Command对象
/// Command要设置的相关表名
/// 错误参数信息,如果没错误返回空集合
internal List SetCommandValueWithCheck(object entity
, List mappers
, DbCommand cmd, string tableName)
{
List list = new List();
Type entityType = entity.GetType();
foreach (var mapper in mappers)
{
PropertyInfo pInfo = entityType.GetProperty(mapper.PropertyName, PublicInstancePropertyBindingFlags);
if (pInfo == null) throw new Exception(entityType.FullName + "类型不存在" + mapper.PropertyName + "属性");
Type pType = pInfo.PropertyType;
if (pType == typeof(string))
{
//字符串才检验
var checkInvalid = SetCommandValueWithCheck(entity
, pInfo
, mapper.ParameterName
, cmd
, mapper.ColumnName
, tableName);
if (checkInvalid != null)
{
list.Add(checkInvalid);
}
}
else
{
if (CollectionUti.HasItem(list))
{
continue;
}
else
{
this.SetCommandValue(entity, pInfo, mapper.ParameterName, cmd);
}
}
}
return list;
}
///
/// 为DbCommand赋值参数,赋值时添加检测(只检测字符串大小是否大于数据库所设长度)
///
/// 相关实体
/// 属性名称
/// 要复制的采纳数
/// DbCommand命令
/// 字段名
/// 表名
///
internal CheckInvalidValue SetCommandValueWithCheck(object entity, string propertyName
, string parameterName, DbCommand cmd
, string mapperColName, string tableName)
{
Type entityType = entity.GetType();
PropertyInfo pInfo = entityType.GetProperty(propertyName, PublicInstancePropertyBindingFlags);
if (pInfo == null) throw new Exception(entityType.FullName + "类型不存在" + propertyName + "属性");
return SetCommandValueWithCheck(entity
, pInfo
, parameterName
, cmd
, mapperColName
, tableName);
}
///
/// 为DbCommand赋值参数,赋值时添加检测(只检测字符串大小是否大于数据库所设长度)
///
/// 相关实体
/// 属性名称
/// 要复制的采纳数
/// DbCommand命令
/// 字段名
/// 表名
///
internal CheckInvalidValue SetCommandValueWithCheck(object entity, PropertyInfo pInfo
, string parameterName, DbCommand cmd
, string mapperColName, string tableName)
{
object val = pInfo.GetValue(entity, null);
CheckInvalidValue checkInvalidValue = null;
mapperColName = mapperColName.ToUpper();
var schema = DAOManager.LoadTableSchema(tableName, this.DataAccess);
if (!schema.ContainsKey(mapperColName))
{
throw new Exception(mapperColName + "在表" + tableName + "中不存在");
}
DatabaseColumnStruct dbColumnStruct = schema[mapperColName];
//字符串才检查
if (dbColumnStruct.DbType == typeof(string))
{
if (!dbColumnStruct.AllowDBNull && (val == null || val.ToString() == ""))
{
//检查为null不合法
checkInvalidValue = new CheckInvalidValue()
{
DBColumnStruct = dbColumnStruct,
EntityType = entity.GetType(),
PropertyName = pInfo.Name,
Value = val,
InvalidMessage = "不允许为空"
};
}
if (checkInvalidValue == null && val != null)
{
//检查长度
string valString = val.ToString();
if (valString.Length > dbColumnStruct.Size)
{
checkInvalidValue = new CheckInvalidValue()
{
DBColumnStruct = dbColumnStruct,
EntityType = entity.GetType(),
PropertyName = pInfo.Name,
Value = val,
InvalidMessage = "超过数据库预设长度" + dbColumnStruct.Size.ToString()
};
}
}
}
if (checkInvalidValue == null)
{
//为DbCommand赋值
DataAccess.AddInParameter(cmd, parameterName, DbType.String, val ?? (object)DBNull.Value);
}
return checkInvalidValue;
}
///
/// 为DbCommand赋值参数,赋值时添加检测(只检测字符串大小是否大于数据库所设长度)
///
/// 值
/// 参数名称
/// Command对象
/// 对应的字段名称
/// Command要设置的相关表名
/// 错误参数信息,如果没错误返回null
internal CheckInvalidValue SetCommandValueWithCheck(object val, string parameterName
, DbCommand cmd
, string mapperColName
, string tableName)
{
CheckInvalidValue checkInvalidValue = null;
mapperColName = mapperColName.ToUpper();
var schema = DAOManager.LoadTableSchema(tableName, this.DataAccess);
if (!schema.ContainsKey(mapperColName))
{
throw new Exception(mapperColName + "在表" + tableName + "中不存在");
}
DatabaseColumnStruct dbColumnStruct = schema[mapperColName];
//字符串才检查
if (dbColumnStruct.DbType == typeof(string))
{
if (!dbColumnStruct.AllowDBNull && (val == null || val.ToString() == ""))
{
//检查为null不合法
checkInvalidValue = new CheckInvalidValue()
{
DBColumnStruct = dbColumnStruct,
EntityType = null,
PropertyName = null,
Value = val,
InvalidMessage = "不允许为空"
};
}
if (checkInvalidValue == null && val != null)
{
//检查长度
string valString = val.ToString();
if (valString.Length > dbColumnStruct.Size)
{
checkInvalidValue = new CheckInvalidValue()
{
DBColumnStruct = dbColumnStruct,
EntityType = null,
PropertyName = null,
Value = val,
InvalidMessage = "超过数据库预设长度" + dbColumnStruct.Size.ToString()
};
}
}
}
if (checkInvalidValue == null)
{
//为DbCommand赋值
DataAccess.AddInParameter(cmd, parameterName, DbType.String, val ?? (object)DBNull.Value);
}
return checkInvalidValue;
}
#endregion
#region SetCommandValue
///
/// 为DbCommand赋值参数
///
/// 实体
/// 实体的属性名
/// 参数名
/// DbCommand对象
internal void SetCommandValue(object entity, string propName, string parameterName, DbCommand cmd)
{
PropertyInfo pInfo = entity.GetType().GetProperty(propName);
SetCommandValue(entity, pInfo, parameterName, cmd);
}
///
/// 为DbCommand赋值参数
///
/// 实体
/// 实体的属性
/// 参数名
/// DbCommand对象
private void SetCommandValue(object entity, PropertyInfo pInfo, string parameterName, DbCommand cmd)
{
Type type = pInfo.PropertyType;
object val = pInfo.GetValue(entity, null);
if (type.IsEnum)
{
val = (int)val;
type = typeof(int);
}
if (type == typeof(int))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.Int32, val);
}
else if (type == typeof(decimal))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.Decimal, val);
}
else if (type == typeof(DateTime))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.DateTime, val);
}
else if (type == typeof(double))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.Double, val);
}
else if (type == typeof(long))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.Int64, val);
}
else if (type == typeof(int?))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.Int32, GetNullableDbValue((int?)val));
}
else if (type == typeof(decimal?))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.Decimal, GetNullableDbValue((decimal?)val));
}
else if (type == typeof(DateTime?))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.DateTime, GetNullableDbValue((DateTime?)val));
}
else if (type == typeof(double?))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.Double, GetNullableDbValue((double?)val));
}
else if (type == typeof(long?))
{
DataAccess.AddInParameter(cmd, parameterName, DbType.Int64, GetNullableDbValue((long?)val));
}
else
{
DataAccess.AddInParameter(cmd, parameterName, DbType.String, val);
}
}
#endregion
#endregion
#region GetPropertyNameByColumnName
///
/// 根据字段名称,寻找属性名称的默认规则
///
/// 字段名称
/// 返回实体属性名称
internal static string GetPropertyNameByColumnName(string colName)
{
return colName.Replace("_", "");
}
#endregion
#region SetEntityUti
///
/// 创建SetEntity的委托
///
/// 实体的类型
///
internal Action CreateSetEntityHandler()
where T : BaseEntity
{
return new Action((_entity, _reader) =>
{
SetEntityUti(_entity, _reader);
});
}
///
/// 从DataReader获取数据到实体
///
/// 实体,不允许为空
/// DataReader对象,不允许为空
internal void SetEntityUti(object entity, IDataReader dr)
{
this.SetEntityUti(entity, dr, delegate
{
return true;
});
}
///
/// 从DataReader获取数据到实体
///
/// 实体,不允许为空
/// DataReader对象,不允许为空
/// 属性与字段名称的映射,Key:为字段名,必须都为大写;Value为属性名
internal void SetEntityUti(object entity, IDataReader dr, Dictionary mapper)
{
SetEntityUti(entity, dr, (_pInfo, _colName) =>
{
if (mapper.ContainsKey(_colName.ToUpper()))
{
SetEntityUti(entity, mapper[_colName.ToUpper()], _colName, dr);
return false;
}
return true;
});
}
///
/// 从DataReader获取数据到实体
///
/// 实体,不允许为空
/// DataReader对象,不允许为空
/// 特殊处理,返回true时,就函数默认处理;返回false,函数就不处理
internal void SetEntityUti(object entity, IDataReader dr, Func action)
{
Type entityType = entity.GetType();
//循环dr的所有字段
int fieldCount = dr.FieldCount;
for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
{
//根据字段名称转换为属性名
string colName = dr.GetName(fieldIndex);
string propertyName = GetPropertyNameByColumnName(colName);
PropertyInfo pInfo = entityType.GetProperty(propertyName, PublicInstancePropertyBindingFlags);
if (action(pInfo, colName) && pInfo != null)
{
SetEntityUti(entity, pInfo, colName, dr);
}
}
}
///
/// 从DataReader获取数据到实体
///
/// 实体,不允许为空
/// 属性名,不允许为空
/// 字段名,不允许为空
/// DataReader对象,不允许为空
/// 一般不建议使用,效率问题
internal void SetEntityUti(object entity, string propName, string colName, IDataReader dr)
{
if (string.IsNullOrEmpty(propName)) throw new NullReferenceException("pInfo不允许为空");
if (entity == null) throw new NullReferenceException("entity不允许为空");
PropertyInfo pInfo = entity.GetType().GetProperty(propName, PublicInstancePropertyBindingFlags);
if (pInfo == null)
{
throw new Exception(propName + "属性在" + entity.GetType().FullName + "不存在");
}
SetEntityUti(entity, pInfo, colName, dr);
}
///
/// 从DataReader获取数据到实体
///
/// 实体,不允许为空
/// 属性对象,不允许为空
/// 字段名,不允许为空
/// DataReader对象,不允许为空
/// 一般不建议使用,效率问题
internal void SetEntityUti(object entity, PropertyInfo pInfo, string colName, IDataReader dr)
{
if (pInfo == null) throw new NullReferenceException("pInfo不允许为空");
if (entity == null) throw new NullReferenceException("entity不允许为空");
Type pType = pInfo.PropertyType;
if (pType == typeof(int))
{
pInfo.SetValue(entity, GetDataByDataReader(dr, colName, DefaultData.INT), null);
}
else if (pType == typeof(decimal))
{
pInfo.SetValue(entity, GetDataByDataReader(dr, colName, DefaultData.DECIMAL), null);
}
else if (pType == typeof(DateTime))
{
pInfo.SetValue(entity, GetDataByDataReader(dr, colName, DefaultData.DATETIME), null);
}
else if (pType == typeof(long))
{
pInfo.SetValue(entity, GetDataByDataReader(dr, colName, DefaultData.LONG), null);
}
else if (pType == typeof(int?))
{
pInfo.SetValue(entity, GetNullableDataByDataReader(dr, colName), null);
}
else if (pType == typeof(decimal?))
{
pInfo.SetValue(entity, GetNullableDataByDataReader(dr, colName), null);
}
else if (pType == typeof(DateTime?))
{
pInfo.SetValue(entity, GetNullableDataByDataReader(dr, colName), null);
}
else if (pType == typeof(Boolean))
{
pInfo.SetValue(entity, GetNullableDataByDataReader(dr, colName), null);
}
else if (pType == typeof(String))
{
if (!string.IsNullOrEmpty(GetDataByDataReader(dr, colName, DefaultData.STRING).Trim()))
{
pInfo.SetValue(entity, GetDataByDataReader(dr, colName, DefaultData.STRING).Trim(), null);
}
else
{
pInfo.SetValue(entity, GetDataByDataReader(dr, colName, DefaultData.STRING), null);
}
}
else if (pType == typeof(long?))
{
pInfo.SetValue(entity, GetNullableDataByDataReader(dr, colName), null);
}
else
{
pInfo.SetValue(entity, GetTrimString(dr, colName).Trim(), null);
}
}
#endregion
#region GetNullableDbValue
///
/// 把可空值的数据转成Db数据
///
///
///
///
internal static object GetNullableDbValue(Nullable val)
where T : struct
{
if (val.HasValue)
{
return val.Value;
}
return DBNull.Value;
}
#endregion
#region 可供自定义创建Database
///
/// 【提供给UnitTest使用】Be convenient for changing the ConnectionString in test.
///
private static CreateDataBaseHandler createDataBaseHandler;
///
/// 【提供给UnitTest使用】Change the default connection string
///
///
public static void SetCreateDataBaseHandler(CreateDataBaseHandler handler)
{
createDataBaseHandler = handler;
}
#endregion
#region CreateDataAccess
///
/// 获取配置文件中的数据库字符串信息,并解密
///
///
///
public static Database CreateDataAccess(string databaseName)
{
Database database = null;
if (createDataBaseHandler == null)
{
//读取Web.Config
var config = ConfigurationManager.ConnectionStrings[databaseName];
//config.ConnectionString = ConnectionStringCryptography.Decrypt(config.ConnectionString);
//解密字符串
ConnectionStringSettings csCopy = new ConnectionStringSettings();
// csCopy.ConnectionString = ConnectionStringCryptography.Decrypt(config.ConnectionString);
csCopy.ConnectionString = config.ConnectionString;
csCopy.ProviderName = config.ProviderName;
csCopy.Name = config.Name;
database = DatabaseFactory.CreateDatabase(csCopy);
}
else
{
database = createDataBaseHandler();
}
return database;
}
#endregion
}
}