一个简单的ORM制作(CURD操作类)

  1. SQL执行类
  2. CURD操作类
  3. 其他酱油类

此篇是为上篇文章填坑的,不知道上篇砸过来的砖头够不够,不够的话请大家继续砸。

CURD操作类负责将用户提供的条件转换为SQL语句,并提供给IHelper执行,返回Model集合.

CURD类需要一个接口抽象出公共方法.便于修改和扩展,提供泛型接口。为了简单起见暂时未提供JOIN的实现,可以以数据库视图替代

public interface IDbOper<T> : IDisposable where T : new()
    {
       object Insert(T m);//新增MODEL,返回ID,简单起见只做了INT自增
       int Update(string str);//批量更新
       int Update(T m);//Model更新
       int Delete();//删除
        ///拼接字符版,需要自己防止注入,特别是Orderby容易被忽视
       IDbOper<T> Select(string sl);//选择字段
       IDbOper<T> Where(string sl);
       IDbOper<T> Orderby(string orby);
        ///Expression版重载,转化为参数方式执行,以参数方式拼接无注入风险 
       IDbOper<T> Select(Expression<Func<T, object>> sl);
       IDbOper<T> Where(Expression<Func<T, bool>> sl);
       ///Dictionary版重载,需要牛顿JSON帮忙转化,以参数方式拼接无注入风险,此方式用于“等于”等查询方式,不提供大于小于查询
       IDbOper<T> Orderby(Dictionary<string, string> dic);
       IDbOper<T> Where(Dictionary<string, object> dic);
        ///
       IDbOper<T> Index(int i);
       IDbOper<T> Size(int i);
       T First();//获取第一个model
       void BegTran();
       void RollBack();
       void Commit();
       M ToObj<M>(Func<IDataReader, M> func,string sql);
       List<T> ToList();
     //转化为其他类型,若开启了事务的话需要此转化
       IDbOper<M> ToOper<M>() where M : new();
       int Count();
       //直接执行SQL语句
       int DoCommand(string sql, bool issp);
    }

由于比较喜欢JQ的操作方式,所以想将这种执行方式带到后台操作数据库,废话不说了先定义2个Model和实例化一个操作类

public class User
{
     [Key]
     public int ID{get;set;}
     public string UserName{get;set;}
     public string Password{get;set;}
}
public class NewUser
{
     [Key]
     public int ID{get;set;}
     public string UserName{get;set;}
     public string Password{get;set;}
}
var db=new DbOper<User>(new DbInfo(){DbType="…",DbConntion="…"}); 

表达式的执行

User a=db.Select(u=>new{u.ID}).Where(u=>u.ID==54).First();

文本拼接的执行

User a=db.Select("*").Where("ID=54").First();

字典拼接的执行

User a=db.Select("*").Where(new Dictionary<string, object>(){Key="ID",Value=54}).First();

分页代码

List<User> lt=db.Select("*").Where("ID>0").Orderby("ID Desc").Index(2).Size(20).ToList();

事务的运用

db.BegTran();
try{
    int b=db.Where("ID=54").Delete();//user表删除ID=54
    int c=db.ToOper<NewUser>().Insert(new NewUser(){UserName="…",Password="…"});//newuser表新增一条记录
    db.Commit();
}
catch{db.RollBack();}

只有当调用Insert,Update,Delete,Count,ToList方法才会开始拼接文本再调用IHelper执行SQL语句,调用完成后会自动调用Clear()来清理保存的where,select等信息。

以下是我提供一个操作类的实现,大家也可以实现自己的操作类。

internal class DbOper<T> :IDbPhysiceOper<T>, IDisposable where T : new()
    {
        internal IHelper db;
        internal StringBuilder where;
        internal StringBuilder select;
        internal StringBuilder orderby;
        internal List<IDataParameter> ps;
        internal StringBuilder sqlinfo;
        internal int index = 0;
        internal int size = OrmGlobal.PageSize;//提供一个默认分页大小
        private DbOper(IHelper h, StringBuilder w, StringBuilder s, StringBuilder or, List<IDataParameter> p,StringBuilder sql)
        {
            db = h;
            where = w;
            select = s;
            orderby = or;
            sqlinfo = sql;
            ps = p;
        }
        internal DbOper(DbInfo info)
        {            //db为上篇上定义的数据库操作类,分分种切换到其他数据库            if (info.DbType.Equals("mssql"))
            {
                db = new Helper.Mssql(info.DbConntion);
            }
            else if (info.DbType.Equals("msmars"))
            {
                db = new Helper.MsMars(info.DbConntion);
            }
            else if (info.DbType.Equals("mysql"))
            {
                db = new Helper.Mysql(info.DbConntion);
            }
            where = new StringBuilder();
            select = new StringBuilder();
            orderby = new StringBuilder();
            sqlinfo = new StringBuilder();
            ps = new List<IDataParameter>();
        }
        public object Insert(T m)
        {
            try
            {
                StringBuilder fields = new StringBuilder();
                StringBuilder values = new StringBuilder();
                List<IDataParameter> lt = new List<IDataParameter>();
                string tp = string.Empty; object o = null;
                foreach (var n in m.GetType().GetProperties())
                {
                    if (n.GetCustomAttributes(typeof(ExcludeColumn), false).Length > 0) { continue; }
                    if (n.GetCustomAttributes(typeof(Key), false).Length > 0) { continue; }
                    o = n.GetValue(m,null);//4.5o = n.GetValue(m);
                    if (o == null) { continue; }
                    fields.Append(n.Name + ",");
                    tp = db.ParStr(n.Name);
                    values.Append(tp + ",");
                    lt.Add(db.Cp(tp, o));
                }
                if (fields.Length > 0) { fields.Length--; }
                if (values.Length > 0) { values.Length--; }
                tp = "INSERT INTO " + typeof(T).Name + "(" + fields.ToString() + ")VALUES(" + values.ToString() + ") " + db.GetIdStr;
                if (OrmGlobal.isrecord) { Record(tp); }
                object a = db.ExectueScalar(tp, lt, false);
                Clear();
                return a;
            }
            catch
            {
                OrmGlobal.DoErr(sqlinfo.ToString()); throw;
            }
        }
        public int Update(string str)
        {
            try
            {
                string tp = "UPDATE " + typeof(T).Name + " SET " + str + (where.Length > 0 ? " WHERE " + where : string.Empty);
                if (OrmGlobal.isrecord) { Record(tp); }
                int i = db.ExecuteQuery(tp, ps, false);
                Clear();
                return i;
            }
            catch
            {
                OrmGlobal.DoErr(sqlinfo.ToString()); throw;
            }
        }
        public int Update(T m)
        {
            try
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("UPDATE " + typeof(T).Name + " SET ");
                List<IDataParameter> lt = new List<IDataParameter>();
                object o = null;
                foreach (var n in m.GetType().GetProperties())
                {//需要定义一个特性Key,以便更新Model                    o = n.GetValue(m,null);//4.5o = n.GetValue(m);
                    if (o == null) { continue; }
                    if (n.GetCustomAttributes(typeof(Key), false).Length > 0)
                    {
                        where.Append((where.Length > 0 ? " AND " : string.Empty) + n.Name + "=" + db.ParStr(n.Name));
                        lt.Add(db.Cp(db.ParStr(n.Name), o));
                        continue;
                    }
                    sb.Append(n.Name + "=" + db.ParStr(n.Name) + ",");
                    lt.Add(db.Cp(db.ParStr(n.Name), o));
                }
                if (sb.Length > 0) { sb.Length--; }
                if (where.Length > 0) { sb.Append(" WHERE " + where); }
                var sql = sb.ToString();
                if (OrmGlobal.isrecord) { Record(sql); }
                int i = db.ExecuteQuery(sql, lt, false);
                Clear();
                return i;
            }
            catch
            {
                OrmGlobal.DoErr(sqlinfo.ToString()); throw;
            }
        }
        public int Delete()
        {
            try
            {
                string sql = "DELETE FROM " + typeof(T).Name + (where.Length > 0 ? " WHERE " + where : string.Empty);
                if (OrmGlobal.isrecord) { Record(sql); }
                int i = db.ExecuteQuery(sql, ps, false);
                Clear();
                return i;
            }
            catch
            {
                OrmGlobal.DoErr(sqlinfo.ToString()); throw;
            }
        }
        public IDbOper<T> Select(string sl)
        {
            if (string.IsNullOrEmpty(sl)) { return this; }
            select.Append((select.Length > 0 ? "," : string.Empty) + sl); return this;
        }
        public IDbOper<T> Select(Expression<Func<T, object>> sl)
        {
            string tp=null;
            using (var tp1 = new LinqVisitor())
            {
                tp=tp1.VisitNew(sl.Body as NewExpression);
            }
            return Select(tp);
        }
        public IDbOper<T> Where(Dictionary<string, object> dic)
        {
            if (dic == null || dic.Count == 0) { return this; }
            var sb = new StringBuilder(); string tp;
            foreach (var n in dic)
            {
                if (sb.Length > 0) { sb.Append(" AND "); }
                sb.Append(n.Key);
                if (n.Value is string)
                {
                    tp = n.Value.ToString();
                    if (tp.Substring(tp.Length - 1, 1) == "*")
                    {
                        sb.Append(" LIKE ");
                        tp = tp.Substring(0, tp.Length - 1) + "%";
                    }
                    else { sb.Append("="); }
                    ps.Add(db.Cp(db.ParStr(n.Key), tp));
                }
                else
                {
                    sb.Append("=");
                    ps.Add(db.Cp(db.ParStr(n.Key), n.Value));
                }
                sb.Append(db.ParStr(n.Key));
            }
            Where(sb.ToString());
            return this;
        }
        public IDbOper<T> Where(string sl)
        {
            if (string.IsNullOrEmpty(sl)) { return this; }
            where.Append((where.Length > 0 ? " AND " : string.Empty) + sl); return this;
        }
        public IDbOper<T> Where(Expression<Func<T, bool>> sl)
        {
            List<object> tp=null;             //需要解析表达式树            using (var tp1 = new LinqVisitor())
            {
                tp = tp1.Visit(sl) as List<object>;
                StringBuilder sb = new StringBuilder(); string s = string.Empty;
                for (int i = 0; i < tp.Count; i += 4)
                {
                    s = db.ParStr(tp[i].ToString());
                    sb.Append(tp[i].ToString() + tp[i + 1].ToString() + s);
                    if (i + 4 < tp.Count) { sb.Append(tp[i + 3]); }
                    ps.Add(db.Cp(s, tp[i + 2]));
                }
                Where(sb.ToString());
            }
            return this;
        }
        public IDbOper<T> Orderby(string orby)
        {
            if (string.IsNullOrEmpty(orby)) { return this; }
            orderby.Append((orderby.Length > 0 ? "," : string.Empty) + orby); return this;
        }
        public IDbOper<T> Orderby(Dictionary<string, string> dic)
        {
            if (dic.Count == 0) { return this; }
            StringBuilder sb = new StringBuilder();
            foreach (var n in dic.Keys)
            {
                if(string.Compare("DESC",dic[n],true)!=0 && string.Compare("ASC",dic[n],true)!=0){continue;}
                sb.Append(n + " " + dic[n] + ",");
            }
            if (sb.Length > 0) { sb.Length--; }
            Orderby(sb.ToString()); return this;
        }
        public IDbOper<T> Index(int i) { if (i > 0) { index = i; } return this; }
        public IDbOper<T> Size(int i) { if (i > 0) { size = i; } return this; }
        public void BegTran() { db.BegTran(); }
        public void RollBack() { db.RollBack(); }
        public void Commit() { db.Commit(); }
        public void Clear()
        {
            where.Length = 0; select.Length = 0; orderby.Length = 0; ps.Clear(); index = 0; size = OrmGlobal.size;
        }
        public M ToObj<M>(Func<IDataReader, M> func, string sql)
        {
            try
            {
                if (OrmGlobal.isrecord) { Record(sql); }
                var rd = db.ExectueReader(sql, ps, false);
                M t = func(rd);
                rd.Close(); Clear();
                return t;
            }
            catch
            {
                OrmGlobal.DoErr(sqlinfo.ToString()); throw;
            }
        }
        public List<T> ToList()
        {
            string sql = GetSql();
            return ToObj<List<T>>(rd => ToList(rd),sql);
        }        //返回List<T>类型        public List<T> ToList(IDataReader rd)
        {
            var lt = new List<T>();
            var set = DelegateExpr.SetMethod(typeof(T));//ExpressTree实现属性绑定,以提高Model赋值性能,可以以反射代替
            while (rd.Read())
            {
                var m = new T();
                for (var i = 0; i < rd.FieldCount; i++)
                {
                    if (rd[i] == DBNull.Value || rd[i] == null) { continue; }
                    set(m, rd.GetName(i).ToLower(), rd[i]);
                }
                lt.Add(m);
            }
            return lt;
        }
        public string GetSql()
        {
            return db.CreateSql(select.ToString(), typeof(T).Name, where.ToString(), orderby.ToString(), size, index);
        }
        public IDbOper<M> ToOper<M>() where M:new()
        {
            Clear();
            return new DbOper<M>(db,where,select,orderby,ps,sqlinfo);
        }
        public int Count()
        {
            try
            {
                string sql = "SELECT COUNT(*) FROM " + typeof(T).Name + (where.Length > 0 ? " WHERE " + where : string.Empty);
                if (OrmGlobal.RecordLog) { Record(sql); }
                int i= (int)db.ExectueScalar(sql, ps, false);
                Clear();
                return i;
            }
            catch
            {
                OrmGlobal.DoErr(sqlinfo.ToString()); throw;
            }
        }
        public int DoCommand(string sql,bool issp)
        {
            int i=db.ExecuteQuery(sql,ps,issp);
            Clear();
            return i;
        }
        public void Dispose()
        {
            where = null; select = null; orderby = null; db.Dispose(); ps = null; sqlinfo = null;
            GC.SuppressFinalize(this);
        }
        public T First()
        {
            var lt=Size(1).Index(1).ToList();
            if (lt.Count > 0) { return lt[0]; }
            return default(T);
        }
        ~DbOper()
        {
            Dispose();
        }
    }

时间: 2024-10-03 06:30:11

一个简单的ORM制作(CURD操作类)的相关文章

一个简单的ORM制作(SQL帮助类)

一个简单的ORM制作大概需要以下几个类: SQL执行类 CURD操作类 其他酱油类 先从SQL执行类说起,可能会涉及数据库的迁移等问题,所以需要定义一个接口以方便迁移到其他数据库, 事务没提供命名,若需要命名可修改为可变参数,IHelper代码如下: internal interface IHelper:IDisposable { int ExecuteQuery(string txt, IEnumerable<IDataParameter> ps, bool issp);//用于执行INSE

一个简单的顺序表基础操作示例

最近学计算机软件基础,学到了线性表.下面就将线性表中最简单的顺序表的一个简单示例贴出,方便大家探讨.(以及后面对函数传参的一个小分析,其实这才是重点) 1 ////需求分析 2 //1.线性表递增有序,删除重复元素 3 //2.线性表逆置 4 //3.寻求最大值 5 6 #include<stdio.h> 7 8 typedef int ElementType; 9 typedef struct _struct 10 { 11 ElementType SequenceList[100]; 12

57-005-3 bootstrap实现一个简单的项目案例--新闻操作(基于jsp无刷新异步操作)

图文版页面:http://note.youdao.com/share/?id=fc2d42d8ce97bea6f3272c02e92a2d23&type=note 资源文件下载:https://yunpan.cn/OcRdu34JqpRdtw 访问密码 67af 3.1 本项目的将按照企业标准开发流程,将程序分成几个层次,同时使用mysql数据库,IDEA开发工具 3.2 本程序主要是对新闻数据(编号.标题.发布日期.内容)的一个维护,具体要求: a. 业务层--增加新闻数据 数据层--新闻表中

开源组件:(4)用元数据和BeanUtils写一个简单的ORM映射BaseDAO.java

1.JDBC元数据 在jdbc中可以使用: 数据库元数据.参数元数据.结果集元数据 (1)数据库元数据 通过Connection对象的getMetaData() 方法可以得到DatabaseMetaData对象.DatabaseMetaData对象包含了数据库的元信息. DatabaseMetaData java.sql.Connection.getMetaData() Retrieves a DatabaseMetaData object that contains metadata abou

登录一个简单的网页进行的操作

HTTP大致来讲就是一种协议 响应与请求一个普通网页大概分为几块 1.查找DNS (1)寻找浏览器自身缓存的DNS (2)寻找自身系统缓存的DNS (3)查找本地的HOST文件 (4)运营商本地缓存的DNS调用 2.根据DNS解析请求返回到系统与浏览器,得到IP地址 3.根据IP地址来一个三次握手(大致就是两者询问三次) 4.服务器请求回来 5.返回HTML解析CSS与HTML等等 6.返回一个完整的页面是

用php实现一个简单的链式操作

最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen(trim($str)); 那么能否实现下面这种写法呢? $str->trim()->strlen(); 下面就来试下. 链式操作,说白了其实就是链式的调用对象的方法.既然要实现字符串的链式操作,那么就要实现一个字符串类,然后对这个类的对象进行调用操作.我对字符串类的期望如下:(1)当我创建对象时,

Python学习第三天(一个简单制作导入模块)

Python一个简单的模块制作和导入 一个简单的模块 [[email protected] python]# cat my.py name = 'I am wuang!' 导入模块 >>> import my >>> print my.name I am wuang! 直接导入模块属性名字 >>> from my import name >>> print name I am wuang!

PHP 数据库操作类:ezSQL

EZSQL类介绍: 下载地址:http://www.jb51.net/codes/26393.html ezsql是一个小型的快速的数据库操作类,可以让你很容易地用PHP操作各种数据库( MySQL.oracle8/9 .interbase.FireBird.PostgreSQL.MS-SQL.sqlite.sqlite C++). 在你的脚本开头是要包含一个一个PHP文件.然后,你就可以使用更小.更容易的一套ezsql函数来代替标准的PHP数据库函数. 它会自动缓存的查询结果,提供了一系列简单

应用程序框架实战十二:公共操作类开发技巧(初学者必读)

本文专门为初学者而写,因为很多初学者可能还不了解公共操作类的作用和封装技巧,大部分有经验的程序员都会把自己所碰到的技术问题整理封装成类,这就是公共操作类.公共操作类往往具有一些通用性,也可能专门解决某些棘手问题.公共操作类是应用程序框架的核心,主要目标是解决大部分技术问题.我将在本文介绍封装公共操作类的要点,供初学者参考. 开发公共操作类的原因 很多初学者会奇怪,.Net Framework提供的API相当易用,为何还要多此一举,进行一层封装呢.下面列举封装公共操作类的一些动机. .Net Fr