zoukankan      html  css  js  c++  java
  • 一个ORM的实现(附源代码)

    1  前言

    经过一段时间的编写,终于有出来一个稳定的版本,期间考虑了多种解决方案也偷偷学了下园子里面大神们的作品。

    已经有很多的ORM框架,为什么要自己实现一个?我的原因是在遇到特殊需求时,可以在ORM中加入特定的代码。如 :根据数据库的字段长度和可空性做基本的数据验证,在ORM中解决数据修改时的同步问题…

    本文主要关注的是如何实现ORM方面,其它的大家可以参考以下两篇文章:

    用T4 Template生成代码:参考此文,可以知道本ORM是如何根据数据库,生成实体层代码。有了这个基础,就可以看懂本文本中所有的T4模板。

    DBHelper (支持事务与数据库变更):参考此文,可以知道本ORM是如何访问数据库,如何支持事务,分页和多种数据库。

    2  实现方法

    本文主要关注的蓝色ORM部分。

    Model:定义了实体的基类。每一张表都会生成对应的实体并继承此类;

    ModelMapping:定义了一张表的结构信息,其中包含了表名、主键、字段类型等。每一张表都会生成一个;

    ModelMappingReflector: 在程序第一次运行时,反射所有ModelMapping的子类,并将其加入一个字典集合中;

    DataAccess<T>: 此类的作用时,根据实体和实体的结构信息(ModelMapping),自动生成SQL来访问数据库(Add,Update,Delete);或将数据库中值加到实体上(GetModel,GetList)。此类帮我们做CRUD的工作,我们不再需要写每张表基本的增删改查的工作了,但仍需要写复杂业务的查询。每一张表都会生成一个空的dao类并继承此类。

    此ORM的核心类就是DataAccess<T>, 下面我们就拿Add作为示例:

    Add 操作代码

    public int Add(T model)
    {
        if (model == null)
        {
            throw new ArgumentNullException();
        }
    
        StringBuilder cmdText = new StringBuilder();
        cmdText.Append("INSERT INTO ").Append(modelMapping.TableName).Append(" (");
        cmdText.Append(string.Join(",", model.ColumnValues.Keys.ToArray()));
        cmdText.Append(") VALUES (@");
        cmdText.Append(string.Join(", @", model.ColumnValues.Keys.ToArray()));
        cmdText.Append(")");
    
        List<DbParameter> dbParms = new List<DbParameter>();
        foreach (var pair in model.ColumnValues) 
        {
            dbParms.Add(DBHelper.CreateInDbParameter(string.Format("@{0}",pair.Key), modelMapping.ColumnDict[pair.Key].DbDataBype, pair.Value));
        }
    
        return this.ExecuteNonQuery(CommandType.Text, cmdText.ToString(), dbParms.ToArray());
    }

    当我们写这样的代码时User model=new User(); model.UserName时,实际上会向Model中ColumnValues集合中添加数据。而要生成一个INSERT SQL (INSERT INTO tablename (column1,colum2) VALUES (@column1,@column2)和添加插入参数,我们需要表名,列名,列值和列的类型。在列名和列值就存在于Model中的ColumnValues集合,而列的类型和表名,我们可以在ModelMapping中获取。

    3   示例

    static void Main(string[] args)
    {
        TestORM();
        TestPaging();
    
        Console.ReadLine();
    }
    
    static void TestORM()
    {
        UserDao dao = new UserDao();
        try
        {
            dao.BeginTransaction();
            // add model
            User mUser1 = new User();
            mUser1.ID = "1";
            mUser1.UserName = "Mike1";
            mUser1.UserPwd = "1234";
            mUser1.CreateBy = "System";
            mUser1.CreateDate = DateTime.Now;
            dao.Add(mUser1);
    
            Console.WriteLine("Create Model Successfully.");
            string cmdText = "SELECT * FROM TUser WHERE ID='1' ORDER BY ID;";
            List<User> list0 = dao.GetListBySQL(cmdText);
            foreach (User model in list0)
            {
                Console.WriteLine(model.UserName);
            }
            Console.WriteLine("Get List Successfully.");
    
            //嵌套事务
            UserDao dao2 = new UserDao();
            try
            {
                dao2.BeginTransaction();
                //update model
                User mUser2 = new User();
                mUser2.ID = "1";
                mUser2.UserName = "Mike.Jiang";
                mUser2.UserPwd = null;
                mUser2.CreateDate = null;
                dao.Update(mUser2);
                Console.WriteLine("Update Model Successfully.");
    
                User mUser3 = dao.GetModel("1");
                if (mUser3 != null)
                    Console.WriteLine(mUser3.UserName);
    
                Console.WriteLine("Get Model Successfully.");
                dao2.CommitTransaction();
            }
            catch
            {
                dao2.RollbackTransaction();
            }
    
            dao.Delete("1");
    
            Console.WriteLine("Delete Model Successfully.");
            dao.CommitTransaction();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            dao.RollbackTransaction();
        }
    }
    
    static void TestPaging()
    {
        UserDao dao = new UserDao();
        // add 100 user
        for (int i = 1; i <= 100; i++)
        {
            User mUser1 = new User();
            mUser1.ID = i.ToString();
            mUser1.UserName = "Mike" + i.ToString();
            mUser1.UserPwd = "1234";
            mUser1.CreateBy = "System";
            mUser1.CreateDate = DateTime.Now;
            dao.Add(mUser1);
        }
    
        string cmdText = string.Format("SELECT * FROM TUser");
        DataTable table = DBHelper.ExecutePagingDataTable(CommandType.Text, cmdText, 1, 10, "ORDER BY ID");
    
        foreach (DataRow row in table.Rows)
        {
            Console.WriteLine(row["ID"]);
        }
    
        Console.WriteLine("Get Datatabe paging successfuly.");
    
        List<User> list = dao.GetListPaging(cmdText, 2, 10, "ORDER BY ID");
        foreach (User m in list)
        {
            Console.WriteLine(m.ID);
        }
    
        Console.WriteLine("Get Model list paging successfully.");
    
    
        cmdText = "DELETE FROM TUser";
        dao.ExecuteNonQuery(CommandType.Text, cmdText);
    }
    View Code

     

    4  总结

    这个版本的ORM示例,示例是没有认真去写了,因为不认为会有人用。但是这个ORM的代码是我认为比较简单的一个版本,只具有ORM的核心功能,几个类,只要具有c#基础的人都能看懂,有兴趣的可以看下。后续,自己会加上分页的Pager相关的内容、数据同步、数据验证的功能和和根据SQL自动生成实体对象的功能。

    所有的源代码: BaseProject.7z

  • 相关阅读:
    Linux命令之_Cut(转)
    Use “error_messages” in Rails 3.2? (raises “undefined method” error)
    ruby错误
    Linux SvN操作
    Linux 安装SVN服务器 (转)
    删除 vim 命令
    vscode 配置java开发
    java json
    svn
    采样率和比特率
  • 原文地址:https://www.cnblogs.com/dataadapter/p/3879504.html
Copyright © 2011-2022 走看看