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

一个简单的ORM制作大概需要以下几个类:

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

先从SQL执行类说起,可能会涉及数据库的迁移等问题,所以需要定义一个接口以方便迁移到其他数据库,

事务没提供命名,若需要命名可修改为可变参数,IHelper代码如下:

internal interface IHelper:IDisposable
    {
       int ExecuteQuery(string txt, IEnumerable<IDataParameter> ps, bool issp);//用于执行INSERT,UPDATE
       object ExectueScalar(string tex, IEnumerable<IDataParameter> ps, bool issp);//执行COUT()
       IDataReader ExectueReader(string tex, IEnumerable<IDataParameter> ps, bool issp);//执行SELECT
       void BegTran();//开始事务
        void RollBack();//回滚
        void Commit();//提交
        string CreateSql(string select, string tbname, string where, string orderby, int size, int index);//数据库的不同,产生的SQL也可能不同,所以必须提供不同的生成方案
        IDataParameter Cp(string name, object value);//创建参数
        string GetIdStr { get; }//获取INSERT产生ID的SQL代码,可能各个数据库不太相同
        string ParStr(string name);//参数标示符,比如MSSQL:@NAME, MYSQL:?NAME,ODBC直接返回?无命名
    }

以上为我个人能思考到的数据库差异和基础功能,若有其他请大家指教

通用MsSql帮助类代码如下:

class Mssql:IHelper
    {
        SqlCommand cmd;
        SqlConnection con;
        SqlTransaction tran;
        internal Mssql(string constr)
        {
            con = new SqlConnection(constr);//test
            cmd = new SqlCommand();
            cmd.Connection = con;
        }
        void SetCmd(string str, IEnumerable<IDataParameter> ps, bool issp)
        {
            cmd.CommandText = str;
            cmd.CommandType = issp ? CommandType.StoredProcedure : CommandType.Text;
            cmd.Parameters.Clear();
            foreach (var n in ps) { cmd.Parameters.Add(n); }
        }
        void CloseCon(){if (con.State == ConnectionState.Open) { con.Close(); }}
        void OpenCon() { if (con.State == ConnectionState.Closed) { con.Open(); } }
        int IHelper.ExecuteQuery(string str, IEnumerable<IDataParameter> ps, bool issp)
        {
            try
            {
                SetCmd(str, ps, issp);
                OpenCon();
                return cmd.ExecuteNonQuery();
            }
            finally{if(tran==null){CloseCon();}}
        }
        object IHelper.ExectueScalar(string str, IEnumerable<IDataParameter> ps, bool issp)
        {
            try
            {
                SetCmd(str, ps, issp);
                OpenCon();
                return cmd.ExecuteScalar();
            }
            finally{if(tran==null){CloseCon();}}
        }
        IDataReader IHelper.ExectueReader(string str, IEnumerable<IDataParameter> ps, bool issp)
        {
            SetCmd(str, ps, issp);
            OpenCon();
            return cmd.ExecuteReader(tran==null?CommandBehavior.CloseConnection:CommandBehavior.Default);
        }
        void IHelper.BegTran() { OpenCon(); tran = con.BeginTransaction(); cmd.Transaction = tran; }
        void IHelper.Commit() { if (tran != null) { tran.Commit(); con.Close(); tran = null; } }
        void IHelper.RollBack() { if (tran != null) { tran.Rollback(); con.Close(); tran = null; } }
        string IHelper.CreateSql(string select, string tbname, string where, string orderby, int size, int index)
        {
            StringBuilder sb = new StringBuilder();//分页需要排序
            sb.Append("SELECT ");
            if (index == 1) { sb.Append("TOP " + size + " "); }
            sb.Append(select+" FROM ");
            if (index > 1){sb.Append("(SELECT ROW_NUMBER() OVER(" + (!string.IsNullOrEmpty(orderby)?"ORDER BY "+orderby:string.Empty) + ") AS ROWID," + select + " FROM ");}
            sb.Append(tbname);
            sb.Append(!string.IsNullOrEmpty(where) ? " WHERE " + where : string.Empty);
            if (index > 1)
            {
                sb.Append(") AS " + tbname + " WHERE ROWID BETWEEN " + ((index - 1) * size + 1) + " AND " + size * index);
            }
            else
            {
                sb.Append(!string.IsNullOrEmpty(orderby) ? " ORDER BY " + orderby : string.Empty);
            }
            return sb.ToString();
        }
        IDataParameter IHelper.Cp(string name, object value) { return new SqlParameter(name, value); }
        string IHelper.ParStr(string name) { return "@"+name;}
        string IHelper.GetIdStr { get { return "SELECT @@IDENTITY"; } }
        void IDisposable.Dispose()
        {
            CloseCon(); con.Dispose(); cmd.Dispose();
        }
    }

MsSql2005开始支持MARS,默认为关闭状态,也可以重写个支持MARS的Help,默认开启2个连接,一个用于查询一个用于无事物的执行,代码如下:

class MsMars:IHelper//自动开启mars,连接0为查询连接,连接1为执行无事务连接,事务连接为新连接
    {
        static SqlConnectionStringBuilder ssb;
        static SqlConnection[] globalCon;
        static object ck = new object();
        public MsMars(string constr)
        {
            if (ssb == null)
            {
                ssb = new SqlConnectionStringBuilder(constr); ssb.MultipleActiveResultSets = true;
            }
        }
        static SqlCommand GetCmd(int i = 3)
        {
            if (ssb == null) { throw new Exception("连接未初始化..."); }
            if (i >= 

3

) { return new SqlConnection(ssb.ConnectionString).CreateCommand(); }
            if (globalCon != null) { return globalCon[i].CreateCommand(); }
            lock (ck)
            {
                if (globalCon != null) { return globalCon[i].CreateCommand(); }
                globalCon = new SqlConnection[2] { new SqlConnection(ssb.ConnectionString), new SqlConnection(ssb.ConnectionString) };
                globalCon[0].Open(); globalCon[1].Open();
            }
            return globalCon[i].CreateCommand();
        }
        SqlCommand cmd;
        void SetCmd(string txt, IEnumerable<IDataParameter> ps, bool issp)
        {
            cmd.Parameters.Clear();
            cmd.CommandText = txt;
            cmd.CommandType = issp ? CommandType.StoredProcedure : CommandType.Text;
            cmd.Parameters.AddRange(ps.ToArray());
        }
        public int ExecuteQuery(string txt, IEnumerable<IDataParameter> ps, bool issp)
        {
            cmd = cmd ?? GetCmd(1);
            SetCmd(txt, ps, issp);
            return cmd.ExecuteNonQuery();
        }
        public object ExectueScalar(string txt, IEnumerable<IDataParameter> ps, bool issp)
        {
            cmd = cmd ?? GetCmd(1);
            SetCmd(txt, ps, issp);
            return cmd.ExecuteScalar();
        }
        public IDataReader ExectueReader(string txt, IEnumerable<IDataParameter> ps, bool issp)
        {
            cmd =cmd??GetCmd(0);
            SetCmd(txt, ps, issp);
            return cmd.ExecuteReader();
        }
        public void BegTran()
        {
            cmd = GetCmd();
            cmd.Transaction = cmd.Connection.BeginTransaction();
        }
        public void RollBack()
        {
            cmd.Transaction.Rollback();
            cmd.Connection.Close();cmd.Dispose();
        }
        public void Commit()
        {
            cmd.Transaction.Commit();
            cmd.Connection.Close(); cmd.Dispose();
        }
        public string CreateSql(string select, string tbname, string where, string orderby, int size, int index)...
        public IDataParameter Cp(string name, object value)...
        public string GetIdStr...
public string ParStr(string name)...
        public void Dispose()...

以上代码本人测试通过,Help类只是ORM的一个起步,曾经看过EF的代码想学习下,但微软的代码实在是太高深(恶心),无从下手,所以我还是按照个人的做法来实现自己ORM,,下篇继续讲CURD操作类.读过觉得还不错请留下你的脚印,谢谢

时间: 2024-10-13 22:29:17

一个简单的ORM制作(SQL帮助类)的相关文章

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

SQL执行类 CURD操作类 其他酱油类 此篇是为上篇文章填坑的,不知道上篇砸过来的砖头够不够,不够的话请大家继续砸. CURD操作类负责将用户提供的条件转换为SQL语句,并提供给IHelper执行,返回Model集合. CURD类需要一个接口抽象出公共方法.便于修改和扩展,提供泛型接口.为了简单起见暂时未提供JOIN的实现,可以以数据库视图替代 public interface IDbOper<T> : IDisposable where T : new() { object Insert(

一个简单的Java 连接SQL Server数据库连接驱动类

import java.sql.*; /** * SQL Server数据库连接类 * @author Administrator * */ public class Sqlsdc { static int a = 0; public Connection sqlsdc(String user, String pwd, String dn) { String url = "jdbc:sqlserver://localhost:1433;databaseName="+dn; final

开源组件:(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

一个简单的游标删除SQL SERVER表

use databaseName declare @tblname char(100) declare @sql char(5000) declare table_cursor cursor for select name  from sysobjects where  name like 'tb_card[_]%'  and name<>'Tb_card_regist' and name<>'Tb_card_item' and name<>'Tb_card_discr

构建一个简单的 linq to sql

先看下运行结果: public class Customer<T> : IQueryable<T>, IOrderedQueryable<T> { public Customer(Expression ex, IQueryProvider Provider) { this.ElementType = typeof(T); this.Expression = ex; this.Provider = Provider; } public Customer() : this(

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!

一个印度人写的VC串口类CSerialCom(有串口基础介绍)

一个由印度人编写的VC串口类(也是一种VC串口控件),他还配合这个类写了VC 串口通信方面的一些基础知识,如怎么用VC打开串口,如何对串口进行配置,读串口.写串口等. 这个类有点特别,它没有使用事件驱动原理,它是以查询方式工作的. 简介: 对没有接触过串口通信的VC程序员来说显得非常困难,很久以前我在 codeguru.com 上搜索过串口通信相关信息得到了非常大的帮助,从那时起能编写一个简单易用的VC 串口类是我的梦想. 经过七个月在串口通信编程方面实践经验后,我编写了一个基于API实现的简单

一个简单的旋转控制器与固定屏幕位置

如下是初步效果图,后面会用在前面的Ogre编辑器中. 开始旋转控制写的比较简单,直接根据鼠标x,y调用yaw与pitch,虽然可用,但是不好用,有时要调到自己想要的方向搞一会,一点都不专业,记的以前好像看过那个软件使用的就是如上这种,分别给出三个方向的圆环,根据鼠标最开始点击的圆环,分别单独调用pitch,yaw,roll,今天花了些时间模仿了下这个,本文记录下. 用的是Axiom,Ogre的C#版,代码差不多可以直接换成MOgre的. 先生成模型,调用了本项目的一些代码,给出相关位置关键代码.

[python] 理解metaclass并实现一个简单ORM框架

metaclass 除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass. metaclass,直译为元类,简单的解释就是: 当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例. 但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类. 连接起来就是:先定义metaclass,就可以创建类,最后创建实例. 所以,metaclass允许你创建类或者修改类.换句话说,你可以把类看成是met