最近看园子里 @李林峰的园子 关于ORM的介绍,真的很好。自己看了也有一点点小心的,记录一下。
ORM即为一种数据模型和数据库中关系映射的一种方式。
学过“三层架构”,知道怎么把表 示层(UI)-->业务逻辑层(BLL)-->数据操作层(DAL)分离开。如下
// //表现层 // protected void submitadd_Click(object sender, EventArgs e) { Model.User user = new Model.User(); user.uid = this.txt_uid.Text.Trim(); user.uname = this.txt_uname.Text.Trim(); user.pwd = this.pwd.Text.Trim(); user.registerDate = DateTime.Now; user.ugender = Int32.Parse(this.ddl_gender.SelectedValue); user.signature = this.signature.Text.Trim(); user.headPic = _imgName.Value; bool result = ulc.InsertNewUser(user); if (result) { this.finishedTips.Visible = true; this.finishedTips.Text = "添加成功"; } else { this.finishedTips.Visible = true; this.finishedTips.Text = "添加失败"; } } // //逻辑层 // public class UserBusinessOpation { /// <summary> /// 更新一条记录 /// </summary> /// <param name="user"></param> /// <returns></returns> public bool UpdateUser(User user) { string sql = "update User_T set uname='" + user.uname + "',pwd='" + user.pwd + "',ugender=" + user.ugender + ",registerDate='" + user.registerDate + "',signature='" + user.signature + "',headPic='" + user.headPic + "' where uid='"+user.uid+"'"; return db.ExecuteInsertOrUpdateSql(sql); } /// <summary> /// 获取某个用户的详细信息 /// </summary> /// <param name="uid"></param> /// <returns></returns> public DataTable GetUserDetail(string uid) { string sql = "select * from User_T where uid='" + uid + "'"; return db.GetTable(sql); } /// <summary> /// 删除某个用户 /// </summary> /// <param name="uid"></param> /// <returns></returns> public bool DeleteUser(string uid) { string sql = "delete from User_T where uid='"+uid+"'"; return db.ExecuteInsertOrUpdateSql(sql); } } // //数据访问层 // pubilc clas DB { private static string ConnString = System.Configuration.ConfigurationManager.ConnectionStrings["SqlServerConn"].ToString(); /*****************************************************************************/ //直接使用sql语句,适用于无参数的调用 #region 执行SQL语句,返回一个DataTable对象 /// <summary> /// 返回一个DataTable对象 /// </summary> /// <param name="strSql">需要执行 的SQL语句</param> /// <returns>DataTable对象</returns> public DataTable GetTable(string strSql) { SqlConnection conn = new SqlConnection(ConnString); conn.Open(); SqlDataAdapter da = new SqlDataAdapter(strSql, conn); DataTable dt = new System.Data.DataTable(); try { da.Fill(dt); return dt; } catch (Exception e) { throw new Exception("执行任务失败:" + e.Message + " " + strSql); } finally { conn.Close(); } } #endregion #region 执行添加,修改,删除的时候进行验证的方法 /// <summary> /// 执行添加的时候进行验证的方法,返回结果的sql更新语句 /// </summary> /// <param name="strSql">需要执行的sql语句</param> /// 返回一个boolean型的值 public Boolean ExecuteInsertOrUpdateSql(string strSql) { SqlConnection conn = new SqlConnection(ConnString); conn.Open(); SqlCommand cmd = new SqlCommand(strSql, conn); try { int count = cmd.ExecuteNonQuery(); if (count > 0) { return true; } else { return false; } } catch (Exception e) { throw new Exception("执行任务失败:" + e.Message + " " + strSql); } finally { conn.Close(); cmd.Dispose(); } } #endregion }
当我第一次遇到这样的“三层代码”模式的时候,我觉得简直酷爆了。整个业务逻辑层被划分的 很清晰。想要什么样的业务逻辑,只需要在业务逻辑层定义数据模型和对模型需要的操作就行。数据访问层的代码完全不用改动。
但是,慢慢我发现,当整个系统的业务比较多的时候,往往在业务逻辑层要写很多的类似的代码。诸如,增删改查,把一个数据模型Model参数传进去之后,对数据模型的进行增删改查极为类似,除了传进去的数据模型Model不一样而已。所以,在多业务时,整个项目的工作量就集中在【重复】业务逻辑层的哪些增删改查的业务。
在阅读了 @李林峰的园子 关于ORM的讲解之后,可以把关注于模型和数据的映射关系,大大滴减少重复的代码工作量。
其中 @李林峰的园子 中使用的ORM使我们可以像如下来写代码。
// //用户表现层 // public void AddMyTest() { News news = new News(); news.newsContent = "习大大发表新年贺词~"; news.newsValue = 200; NewsORM.add(news); } // //业务逻辑层 // public class NewsORM { ... public static void add(Model.News news) { ORM.add(news); } ... } // //数据访问层 // public class ORM { /// <summary> /// 添加一个实体 /// </summary> /// <param name="classObject"></param> /// <returns></returns> public static bool Add(object classObject, string AssemblyName, string ConnString) { int intMaxID = 0, intFlag = 0; return Add(classObject, out intMaxID, intFlag, AssemblyName, ConnString); } /// <summary> /// 添加一个实体并且返回其ID标识 /// </summary> /// <param name="classObject"></param> /// <param name="intMaxID"></param> /// <returns></returns> public static bool Add(object classObject, out int intMaxID, string AssemblyName, string ConnString) { intMaxID = 0; int intFlag = 1; return Add(classObject, out intMaxID, intFlag, AssemblyName, ConnString); } /// <summary> /// 添加实体并判断是否返回最大的编号 /// </summary> /// <param name="classObject"></param> /// <param name="intMaxID"></param> /// <param name="intFlag">当intFlag=0时,则不去取intMaxID,等于1则相反</param> /// <returns></returns> private static bool Add(object classObject, out int intMaxID, int intFlag, string AssemblyName, string ConnString) { //声名输出参数 intMaxID = 0; //获取表名称 string strTableName = Mapping.GetTableName(classObject, AssemblyName); //获取主键字典 Dictionary<string, string> IdentityMapping = Mapping.GetIdentityMapping(classObject, AssemblyName); //获取除主键以外的字段字典 Dictionary<string, string> BaseFieldMapping = Mapping.GetBaseFieldMapping(classObject, AssemblyName); //获取 "属性--值" 字典 Dictionary<string, string> FieldValueMapping = Model.GetValueMapping(classObject, BaseFieldMapping); //创建SQL语句 string strSQL = SQL.CreateInsert(classObject, strTableName, IdentityMapping, BaseFieldMapping, FieldValueMapping, intFlag); //执行SQL return SQL.ExecInsert(strSQL, out intMaxID, intFlag, ConnString); } }
其中,Mapping类是根据模型的类名来获取到其映射的数据库中的映射对应关系。其中每个模型类以及每个模型类的映射关系都需要用户来定义。
如下:
namespace HZYT.Model { //模型类 public class News { public int newsID { set; get; } public string newsContent { set; get; } public int newsValue { set; get; } } } namespace HZYT.Model { //映射类 public class NewsMapping { public static string GetTableName() { return "News_T"; } public static Dictionary<string,string> GetIdentityMapping() { Dictionary<string, string> Identity = new Dictionary<string, string>(); Identity.Add("newID", "id"); return Identity; } public static Dictionary<string,string> GetBaseFieldMapping() { Dictionary<string, string> BaseField = new Dictionary<string, string>(); BaseField.Add("newsContent", "content"); BaseField.Add("newsValue", "value"); return BaseField; } } }
改进后的效果显而易见,我们彻底摆脱了书写那些业务逻辑层的 重复性的 增删改查操作,而这些操作都被ORM抽象地去实现(具体实现肯定要根据 那些映射关系)。而现在我们在写逻辑业务的时候,只需要定义业务逻辑层的数据模型以及其与数据库中的字段映射关系即可。ORM通过反射实现了从业务逻辑层到具体的数据库sql语句的转化,以及到最后的sql语句的执行。
最后 po上我自己画的一个图,图可能不准确,大致反应 了ORM结构图。