ORM小结

最近看园子里 @李林峰的园子 关于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结构图。

时间: 2024-10-21 16:29:29

ORM小结的相关文章

Laravel 的 ORM 返回的数据类型小结

一.简介 Laravel 的数据库查询构造器提供了一个方便.流畅的接口,用来创建及运行数据库查询语句.它能用来执行应用程序中的大部分数据库操作,且能在所有被支持的数据库系统中使用. Laravel 的查询构造器使用 PDO 参数绑定,来保护你的应用程序免受 SQL 注入的攻击.在绑定传入字符串前不需要清理它们. 二.查询 1.从数据表中获取所有的数据列 1. 查询中的 get 与 all 方法返回的是集合. 示例# 你可以使用 DB facade 的 table 方法开始查询.这个 table

.NET轻量级ORM组件Dapper葵花宝典

一.摘要 为什么取名叫<葵花宝典>? 从行走江湖的世界角度来讲您可以理解为一本"武功秘籍",站在我们IT编程的世界角度应该叫"开发宝典". 如果您在工作中主要接触的是操作MySQL数据库,但您又想学习和了解.NET轻量级ORM框架Dapper,那么就请跟着阿笨一起学习本次的分享课<.NET轻量级ORM框架Dapper葵花宝典>.Let's Go,Do It ,Dapper For MySQL! 废话不多说,直接上干货,我们不生产干货,我们只是

【13】Python应用系列--ORM

DB First 通过类和对象操作数据库 Code First 自定义生成表 class 类(base): 列1 列2 根据类创建表 使用类操作表 session.query(类) 1. 创建单表,一对多 rom sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, Foreign

.NET进阶——ORM基础认识

ORM对象关系映射,对象即实体,关系即关系数据库表,ORM即实现从实体对象关系数据库数据的映射.本质上就是将数据从一种形式转换到另一种形式.它具体又有哪些表现呢,咱们一步步学习,一步步分析. ORM解决了什么问题? 想想以前使用的三层开发,在D层对数据库的操作基本可以归纳为以下几点问题: 1.使用DataSet/DataTable填充返回数据. DataSet的结构就相当于一张表,使用DataSet ,需要取得某一数据时是必须要知道表结构的(列名或者列的序号),这不仅违反了三层分层的思想,也不符

.NET轻量级ORM组件Dapper修炼手册

一.摘要 1.1.为什么叫本次的分享课叫<修炼手册>? 阿笨希望本次的分享课中涉及覆盖的一些小技巧.小技能给您带来一些帮助.希望您在日后工作中把它作为一本实际技能手册进行储备,以备不时之需,一旦当手头遇到与Dapper修炼手册中相似用法的地方和场景,可以直接拿来进行翻阅并灵活的运用到项目中.最后阿笨建议您可以根据自己在工作中碰到的不同的使用场景,不断的完善此本修炼手册. 废话不多说,直接上干货,我们不生产干货,我们只是干货的搬运工. 四.涉及覆盖的知识点 1.C# Linq To Xml技术.

《软件工程综合实践》第三次小结

这是最后一次的小结,在这次的实践中,老师带领着我们编写了订单管理系统,其中实现的功能有新增订单信息,删除订单信息,查找订单信息,修改订单信息和将订单信息输出为excel表格.每个功能的实现依次都是从网页上触发相应action然后action启动相应的配置服务,服务启动DAO来执行相应的功能对数据库中的数据进行修改. 新增订单信息的action类: package com.crm.action; import java.util.ArrayList;import java.util.List; i

【ORM】关于Dapper的一些常见用法

引言 Dapper是.Net平台下一款小巧玲珑的开源Orm框架,简单实用的同时保持高性能,非常适合我这种喜欢手写SQL的人使用,下面介绍一下如何使用Dapper. 相关资料 Dapper的GitHub地址是dapper-dot-net,上面有一些用法和性能的介绍,有兴趣者可以上去看看. 数据库设计和实体类     简单设计两个表,分别为部门表,雇员表. CREATE TABLE [dbo].[T_Dept] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Dept]

IbatisNet开发使用小结

一.   介绍 平常做企业级应用,需求变化是经常的事,而很多基础代码重复也是很让人头疼的问题.所以很多人会使用一些ORM框架来增强项目的可维护性.可扩展性.IBatis.Net就是一个比较易用的ORM框架,使用起来较为方便.灵活.IBatis.Net是从Ibatis的Java版本移植过来的.NET版本.iBATIS作为一种独特的Data Mapper,使用SQL映射的方式将对象持久化至关系型数据库.简单的理解就是它将我们在数据访问层实现的C#逻辑代码,变为通过关系数据库与对象的映射,将SQL逻辑

系统变慢调整小结

客户反映系统越用越慢,重启服务器后段时间内系统恢复正常 老年代 垃圾回收不了. full gc 每分钟执行40次左右. 开始以为是内存泄漏,导出jvm内存快照 快照中可以看到线程池里有问题.但是看不出具体的问题原因 导出线程快照 没有发现可疑线程信息...  郁闷了..(当前时间19:21已经没有客户在操作系统了) 第二天继续今天的问题.上午客户打电话说又有问题了. 赶紧导出线程快照 $jstack pid "Running HTTPHandler-26" prio=10 tid=0x