在本节我想与大家与分享一下,我所将要做的权限系统的架构和数据库的表的设计。请各位大神们对我项目中设计的不足之处进行指导,让我得以更好的写完它,留给需要它的人。
我的项目架构如下图所示:
如上图所示,在数据访问层,我采用了抽象工厂的方式,来对数据访问层和业务逻辑层解耦,当然如果你想更高大上一些,可以用第三方的框架,比如Spring.Net ,Autofac来实现。解耦的好处在于可以方便的切换数据库,当数据库变更时,只需换一下对应的数据访问DAL就行,本系列中,我所采用的是SQLServer。写到这我想在如下这个大数据时代,MongoDB其实也是不错的。后面有机会,可以开一个MongoDB的专题和大家一起来使用一下MongoDB学习一下它。对于抽象工厂来实现业务逻辑层与数据访问层的解耦实现代码如下,主要用到了反射,面向接口编程。
配置:
<appSettings> <add key="DAL" value="MCFramework.SQLDAL"/> <!--页容量-->
<add key="PageSize" value=""/> </appSettings>
抽象工厂:
namespace MCFramework.RepositoryFactory
{
public class RepositoryFactory
{
public RepositoryFactory()
{ } private static readonly string AssemblyPath =ConfigurationSettings.AppSettings["DAL"]; #region CreateObject //不使用缓存
private static object CreateObjectNoCache(string AssemblyPath, string classNamespace)
{
try
{
object objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
return objType;
}
catch(System.Exception ex)
{
string str=ex.StackTrace;// 记录错误日志
return null;
} }
//使用缓存
//private static object CreateObject(string AssemblyPath, string classNamespace)
//{
// object objType = DataCache.GetCache(classNamespace);
// if (objType == null)
// {
// try
// {
// objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
// DataCache.SetCache(classNamespace, objType);// 写入缓存
// }
// catch//(System.Exception ex)
// {
// //string str=ex.Message;// 记录错误日志
// }
// }
// return objType;
//}
#endregion /// <summary>
/// 用户仓储
/// </summary>
public static ISystem_EmployeeRepository System_EmployeeRepository { get { return (ISystem_EmployeeRepository)CreateObjectNoCache(AssemblyPath, AssemblyPath + ".System_EmployeeRepository"); } } /// <summary>
///菜单仓储
/// </summary>
public static ISystem_MenuRepository System_MenuRepository { get { return (ISystem_MenuRepository)CreateObjectNoCache(AssemblyPath, AssemblyPath + ".System_MenuRepository"); } } /// <summary>
///角色仓储
/// </summary>
public static ISystem_RoleRepository System_RoleRepository { get { return (ISystem_RoleRepository)CreateObjectNoCache(AssemblyPath, AssemblyPath + ".System_RoleRepository"); } } /// <summary>
///按钮仓储
/// </summary>
public static ISystem_ButtonRepository System_ButtonRepository { get { return (ISystem_ButtonRepository)CreateObjectNoCache(AssemblyPath, AssemblyPath + ".System_ButtonRepository"); } } }
}
所有的访问数据库的操作都用接口来约束:
namespace MCFramework.IDAL
{
public interface IBaseRepository<T> where T:class
{
int Add(T model); int UpdateDel(string ids, bool isDel); int Del(string ids); int Update(T model); DataSet GetListByProc(string procName, System.Data.SqlClient.SqlParameter[] paras); DataSet GetModel(string Id); DataSet GetList(string strWhere); }
}
namespace MCFramework.IDAL
{
public interface ISystem_ButtonRepository:IBaseRepository<System_ButtonModel>
{
bool IsExit(string ButtonCode);
}
}
接口的实现:
namespace MCFramework.SQLDAL
{
/// <summary>
/// Author: MaChun
/// Description: DALTier -- the DAL class of System_Button.
/// Datetime:2015/6/8 13:00:35
/// </summary>
public class BaseSystem_ButtonRepository: IBaseRepository<System_ButtonModel>
{ //创建企业库连接
public SqlDataAccess db = SqlDataAccess.CreateDataAccess(); #region 新增一条记录 Add(System_ButtonModel model)
/// <summary>
/// 新增一条记录
/// </summary>
public int Add(System_ButtonModel model)
{
int result = ;
try
{ StringBuilder strSql = new StringBuilder();
strSql.Append("insert into System_Button(");
strSql.Append("SBT_Guid,SBT_ButtonCode,SBT_ButtonName,SBT_IconUrl,SBT_IconCss,SBT_CreateBy,SBT_CreatedDate)");
strSql.Append(" values (");
strSql.Append("@SBT_Guid,@SBT_ButtonCode,@SBT_ButtonName,@SBT_IconUrl,@SBT_IconCss,@SBT_CreateBy,@SBT_CreatedDate)");
strSql.Append(";select @@IDENTITY");
SqlParameter[] parameters = {
new SqlParameter("@SBT_Guid", SqlDbType.VarChar,),
new SqlParameter("@SBT_ButtonCode", SqlDbType.VarChar,),
new SqlParameter("@SBT_ButtonName", SqlDbType.VarChar,),
new SqlParameter("@SBT_IconUrl", SqlDbType.VarChar,),
new SqlParameter("@SBT_IconCss", SqlDbType.VarChar,),
new SqlParameter("@SBT_CreateBy", SqlDbType.VarChar,),
new SqlParameter("@SBT_CreatedDate", SqlDbType.DateTime,)};
parameters[].Value = model.SBTGuid;
parameters[].Value = model.SBTButtonCode;
parameters[].Value = model.SBTButtonName;
parameters[].Value = model.SBTIconUrl;
parameters[].Value = model.SBTIconCss;
parameters[].Value = model.SBTCreateBy;
parameters[].Value = model.SBTCreatedDate; result = db.ExecuteNonQuery(strSql.ToString(), parameters);
}
catch (Exception ex)
{
throw ex;
}
return result;
}
#endregion #region 逻辑删除 UpdateDel(string ids, bool isDel)
/// <summary>
/// 逻辑删除
/// </summary>
public int UpdateDel(string ids, bool isDel)
{ StringBuilder strSql = new StringBuilder();
strSql.Append("update System_Button set noDelKey='" + isDel.ToString() + "' where SBT_Guid in (" + ids + ")"); return db.ExecuteNonQuery(strSql.ToString());
}
#endregion #region 物理删除 Del(string id)
/// <summary>
/// 物理删除
/// </summary>
public int Del(string id)
{ StringBuilder strSql = new StringBuilder();
strSql.Append("delete System_Button where SBT_Guid ='"+id+"' ");
return db.ExecuteNonQuery(strSql.ToString());
}
#endregion #region 修改记录 Update(System_ButtonModel model)
/// <summary>
/// 修改记录
/// </summary>
public int Update(System_ButtonModel model)
{
int res = -;
StringBuilder strSql = new StringBuilder();
strSql.Append("update System_Button set ");
strSql.Append("SBT_ButtonCode=@SBT_ButtonCode,");
strSql.Append("SBT_ButtonName=@SBT_ButtonName,");
strSql.Append("SBT_IconUrl=@SBT_IconUrl,");
strSql.Append("SBT_IconCss=@SBT_IconCss,");
strSql.Append("SBT_CreateBy=@SBT_CreateBy,");
strSql.Append("SBT_CreatedDate=@SBT_CreatedDate");
strSql.Append(" where SBT_Guid=@SBT_Guid ");
SqlParameter[] parameters = {
new SqlParameter("@SBT_Guid", SqlDbType.VarChar,),
new SqlParameter("@SBT_ButtonCode", SqlDbType.VarChar,),
new SqlParameter("@SBT_ButtonName", SqlDbType.VarChar,),
new SqlParameter("@SBT_IconUrl", SqlDbType.VarChar,),
new SqlParameter("@SBT_IconCss", SqlDbType.VarChar,),
new SqlParameter("@SBT_CreateBy", SqlDbType.VarChar,),
new SqlParameter("@SBT_CreatedDate", SqlDbType.DateTime,)};
parameters[].Value = model.SBTGuid;
parameters[].Value = model.SBTButtonCode;
parameters[].Value = model.SBTButtonName;
parameters[].Value = model.SBTIconUrl;
parameters[].Value = model.SBTIconCss;
parameters[].Value = model.SBTCreateBy;
parameters[].Value = model.SBTCreatedDate; try
{
res = db.ExecuteNonQuery(strSql.ToString(), parameters);
}
catch (Exception ex)
{
throw ex;
}
finally { }
return res;
}
#endregion #region 根据主键查询出DataSet GetModel(string Id)
/// <summary>
/// 根据主键查询出DataSet
/// </summary>
public DataSet GetModel(string Id)
{ StringBuilder strSql = new StringBuilder();
strSql.Append("select SBT_Guid,SBT_ButtonCode,SBT_ButtonName,SBT_IconUrl,SBT_IconCss,SBT_CreateBy,SBT_CreatedDate from System_Button ");
strSql.Append(" where SBT_Guid=@SBT_Guid ");
SqlParameter[] parameters = {
new SqlParameter("@SBT_Guid", SqlDbType.Char,)};
parameters[].Value = Id; DataSet ds = db.ExecuteDataSet(strSql.ToString(), parameters); return ds;
} #endregion #region 根据where 条件查询出DataSet GetList(string strWhere)
/// <summary>
/// 根据where 条件查询出DataSet
/// </summary>
public DataSet GetList(string strWhere)
{ StringBuilder strSql = new StringBuilder();
strSql.Append("select SBT_Guid,SBT_ButtonCode,SBT_ButtonName,SBT_IconUrl,SBT_IconCss,SBT_CreateBy,SBT_CreatedDate ");
strSql.Append(" FROM System_Button ");
if (strWhere.Trim() != "")
{
strSql.Append(" where " + strWhere);
} DataSet ds = db.ExecuteDataSet(strSql.ToString()); return ds;
}
#endregion #region 根据存储过程查询出DataSet GetListByProc(string procName,SqlParameter[] paras)
/// <summary>
///根据存储过程查询出DataSet
/// </summary>
/// <param name="procName">procName</param>
/// <param name="paras">paras</param>
public DataSet GetListByProc(string procName,SqlParameter[] paras)
{ DataSet ds = db.ExecuteDataSet(procName, paras); return ds;
}
#endregion }
}
namespace MCFramework.SQLDAL
{
/// <summary>
/// Author: MaChun
/// Description: DALTier -- the DAL class of System_Button.
/// Datetime:2015/4/20 16:01:42
/// </summary>
public class System_ButtonRepository:BaseSystem_ButtonRepository,ISystem_ButtonRepository
{ public bool IsExit(string ButtonCode)
{
bool flag = false;
string sql = string.Format(@"SELECT * FROM dbo.System_Button WHERE SBT_ButtonCode='{0}'", ButtonCode);
DataSet ds = db.ExecuteDataSet(sql);
if (ds.Tables.Count > )
{
flag = ds.Tables[].Rows.Count > ;
} return flag;
}
}
}
数据访问层操作数据库我没有用ORM框架,用的是传统的ADO.Net,我个人觉得这样可控性会更好,也利于以后的优化。
业务逻辑层的调用:
namespace MCFramework.BLL
{
/// <summary>
/// Author: MaChun
/// Description: BLLTier -- the BLL class of System_Button.
/// Datetime:2015/5/6 17:00:35
/// </summary>
public class BaseSystem_ButtonService
{
protected static readonly ISystem_ButtonRepository dal = RepositoryFactory.RepositoryFactory.System_ButtonRepository; #region 新增一条记录 Add(System_ButtonModel model)
/// <summary>
/// 新增一条记录
/// </summary>
public int Add(System_ButtonModel model)
{
return dal.Add(model);
}
#endregion #region 根据ID 逻辑删除一条记录 UpdateDel(string ids, bool isDel)
/// <summary>
/// 根据ID 逻辑删除一条记录
/// </summary>
public int UpdateDel(string ids, bool isDel)
{
return dal.UpdateDel(ids, isDel);
}
#endregion #region 根据ID物理删除一条记录 Del(string id)
/// <summary>
/// 根据ID物理删除一条记录
/// </summary>
public int Del(string id)
{
return dal.Del(id);
}
#endregion #region 更新一条记录 Update(System_ButtonModel model)
/// <summary>
/// 更新一条记录
/// </summary>
public int Update(System_ButtonModel model)
{
return dal.Update(model);
}
#endregion #region 根据存储过程来查询返回一个list 集合 GetListByProc
/// <summary>
///根据存储过程来查询返回一个list 集合
/// </summary>
/// <param name="procName">procName</param>
/// <param name="paras">paras</param>
public List<System_ButtonModel> GetListByProc(string procName,System.Data.SqlClient.SqlParameter[] paras)
{
DataTable dt= dal.GetListByProc(procName,paras).Tables[]; List<System_ButtonModel> list = null;
list = new List<System_ButtonModel>();
LoadListData(ref list, dt);
if (list.Count > )
{
return list;
}
else
{
return null;
}
}
#endregion #region 根据主键来查询得到一个实体 GetModel(string Id)
/// <summary>
/// 根据主键来查询得到一个实体
/// </summary>
public System_ButtonModel GetModel(string Id)
{ DataTable dt= dal.GetModel(Id).Tables[]; System_ButtonModel model = new System_ButtonModel();
if (dt.Rows.Count > )
{
LoadEntityData(ref model, dt.Rows[]);
return model;
}
else
{
return null;
}
}
#endregion #region 根据 where 条件来查询得到一个list集合 GetList(string strWhere)
/// <summary>
/// 根据 where 条件来查询得到一个list集合
/// </summary>
public List<System_ButtonModel> GetList(string strWhere)
{
DataTable dt= dal.GetList(strWhere).Tables[]; List<System_ButtonModel> list = null;
list = new List<System_ButtonModel>();
LoadListData(ref list, dt);
if (list.Count > )
{
return list;
}
else
{
return null;
} }
#endregion #region 将DataTable转换为 List 对象集合 LoadListData
/// <summary>
/// 将DataTable转换为 List 对象集合
/// </summary>
/// <param name="list">GenericList</param>
/// <param name="dt">DataTable</param>
public void LoadListData(ref List<System_ButtonModel> list, DataTable dt)
{
if (dt.Rows.Count > )
{
System_ButtonModel model;
foreach (DataRow dr in dt.Rows)
{
model = new System_ButtonModel();
LoadEntityData(ref model, dr);
list.Add(model);
}
}
}
#endregion #region 将Datatable中的Dr 转换成 Model 实体 LoadEntityData
/// <summary>
/// 将Datatable中的Dr 转换成 Model 实体
/// </summary>
/// <param name="model">Entity</param>
/// <param name="dr">DataRow</param>
public void LoadEntityData(ref System_ButtonModel model, DataRow dr)
{
model.SBTGuid = dr["SBT_Guid"].ToString();
model.SBTButtonCode = dr["SBT_ButtonCode"].ToString();
model.SBTButtonName = dr["SBT_ButtonName"].ToString();
model.SBTIconUrl = dr["SBT_IconUrl"].ToString();
model.SBTIconCss = dr["SBT_IconCss"].ToString();
model.SBTCreateBy = dr["SBT_CreateBy"].ToString();
if (dr["SBT_CreatedDate"].ToString() != "")
{
model.SBTCreatedDate = DateTime.Parse(dr["SBT_CreatedDate"].ToString());
} }
#endregion }
}
public class System_ButtonService:BaseSystem_ButtonService
{ #region 单例模式 private System_ButtonService()
{
} private static readonly System_ButtonService instance = new System_ButtonService(); public static System_ButtonService Instance
{
get { return instance; }
} #endregion public bool IsExit(string ButtonCode)
{ return dal.IsExit(ButtonCode);
}
}
}
对于,业务层到UI层之间的解耦,我没有按架构图中的去实现,我觉在一般中的项目中没有这个必要,为了简化 ,我所以省去了,如果你想加上,完全可以按抽象工厂的方式加上。以上就是我对整个项目的架构上做的一个说明。接下来我们再看看我数据库的设计。
权限的细化颗粒度到各页面的按钮。对于以上的架构和表设计,如果有什么好的建议可以给我留言。下一节,我们将完成主页面的主休框架和登录验证。