/////////////////////////////////////////////////////////////////////////////
// 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.AMS.Entitys.Common;
using HH.AMS.Common;
#endregion
namespace HH.AMS.DAL {
///
/// 创建Database委托
///
/// 数据访问工具类实例
//public delegate Database CreateDataBaseHandler();
///
/// DAL所有数据访问类的基类
///
/// DAL中的所有数据访问类,都需要继承BaseDAL
public class BaseDAL : BaseDataUtility {
public enum DBTYPE {
MYSQL,
MSSQL,
ORACLE,
ORTHER
}
public static string dbType = ConfigurationManager.ConnectionStrings["DataType"].ToString();
public static DBTYPE Now_dbType {
get {
if (dbType.Equals("MYSQL"))
return DBTYPE.MYSQL;
if (dbType.Equals("MSSQL"))
return DBTYPE.MSSQL;
if (dbType.Equals("ORACLE"))
return DBTYPE.ORACLE;
return DBTYPE.ORTHER;
}
}
public static string GetDate() {
switch (Now_dbType) {
case DBTYPE.MYSQL: return " now() ";
case DBTYPE.MSSQL: return " getDate() ";
case DBTYPE.ORACLE: return " SYSDATE() ";
default: return "";
}
}
///
/// 创建Database委托
///
/// 数据访问工具类实例
public delegate Database CreateDataBaseHandler();
#region 初始化
private Database db;
private string databaseName;
///
/// 默认的数据库连接字符串在配置文件的名称(根据连接配置获得所要连接的数据库)
///
internal static readonly string DATABASE_NAME = "amsConnection";
///
/// 默认根据属性名获取属性对象的策略。
///
private static BindingFlags PublicInstancePropertyBindingFlags = BindingFlags.CreateInstance
| BindingFlags.Instance //实例
| BindingFlags.Public //公有
| BindingFlags.SetProperty //可写属性
| BindingFlags.IgnoreCase; //忽略大小写
///
/// 构造函数
///
public BaseDAL()
: this(DATABASE_NAME) {
}
///
/// 构造函数
///
/// 数据库连接字符串在配置文件的名称
internal BaseDAL(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);
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。
internal 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
}
}