• 一个简单得不能再简单的“ORM”了


    本文适合初学者,老鸟请点赞即走,谢谢。

    文字功底有限,表述不恰当的地方,请各位多多包涵。

    一,核心

          现在ORM已经很多了,功能也齐全了,大家说我这是干无聊的事,造的连车轮子都还不算,反正我就当学习。

          还有就是,下面这个不算正在的ORM,离真正在ORM差的很远的。

          主要思想

          

    二,实例测试

          1,基础数据准备

              1.1 数据库表结构(sqlite数据库)

           

        1.2 实体

          

    复制代码
        public class Msg
        {
            public string Id { get; set; }
            public string Content { get; set; }
            public string Name { get; set; }
            public DateTime CreateTime { get; set; }
        }
    复制代码

       2,开始插入数据

        2.1 创建了一个控制台程序做测试

    复制代码
            string connStr = string.Format("Data Source={0};", System.AppDomain.CurrentDomain.BaseDirectory + "App_Data\db.db");
                WangSql.ISqlExe sqlexe = new WangSql.SqlExe(WangSql.DbType.SQLLITE, connStr);
    
                string sql = "insert into Msg(Id,Content,Name,CreateTime) values(#Id#,#Content#,#Name#,#CreateTime#)";
                Msg model = new Msg()
                {
                    Id = Guid.NewGuid().ToString("N"),
                    Content = "这里是内容",
                    Name = "姓名",
                    CreateTime = DateTime.Now
                };
                sqlexe.NonQuery(sql, model);
    复制代码

        查看下数据呢,

        

        至此,测试成功,再来测试下呢。

        2.2 开8个线程,每个线程循环插入100条数据试试看。

        测试结果:好尴尬sqlite多线程容易锁库,以后操作这个库,还是队列吧,楼主本着不放弃不抛弃的精神,再来了一次。

        

        这次没被锁,数据库数据呢。

        

        数据也没少,OK,测试完成。

    三,源码讲解(准确的是代码讲解)

      3.1 生成SQL

        大家有没有发现,我在执行时传入sql的格式

        insert into Msg(Id,Content,Name,CreateTime) values(#Id#,#Content#,#Name#,#CreateTime#)//有没有很熟悉呢,没错,就是借鉴(山寨)的ibatis的,哈哈

        就是这个样子的,

        表:Msg(Id,Content,Name,CreateTime)

        DbDataParameter:values(#Id#,#Content#,#Name#,#CreateTime#)

        DbDataParameter,这里支持值类型,string,object,object[],以及Hashtable和用户自定义类。

        下面就是生成SQL语句的代码、

    复制代码
            public string SqlInit(string sql, out List<string> paraName)
            {
                string sqlTag = sql;
                List<string> sqlParaName = new List<string>();
                Regex regex = new Regex("(#(.[^#]+?)#)");
                var ms = regex.Matches(sql);
                foreach (Match item in ms)
                {
                    var p1 = item.Groups[1];
                    var p2 = item.Groups[2];
                    sqlTag = sqlTag.Replace(p1.Value, prefix + p2.Value);
                    if (!sqlParaName.Contains(p2.Value))
                        sqlParaName.Add(p2.Value);
                }
                paraName = sqlParaName;
                return sqlTag;
            }
    复制代码

        这个就会生成sql,并且还会把Parameter的key以集合的方式抛出去。

          3.2 实体转成DbDataParameter

        当插入数据,参数传入的是个用户自定义类的话,需要做一次转换。先将实体转成Hashtable,然后再根据3.1生成sql抛出来的Parameter的key来生成Parameter集合。

        

    复制代码
            public static Hashtable ModelToHashtable(object model)
            {
                Hashtable ht = new Hashtable();
                BindingFlags flag = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                PropertyInfo[] propertys = model.GetType().GetProperties(flag);
                foreach (PropertyInfo pi in propertys)
                {
                    string name = pi.Name;
                    if (!pi.CanRead) continue;
                    object value = pi.GetValue(model, null);
                    ht.Add(name, value);
                }
                return ht;
            }
    复制代码

      3.3 完整NonQuery执行代码

    复制代码
            public int NonQuery(string sql, object para)
            {
                if (IsModel(para))//Model入参
                {
                    Hashtable ht = DataMapHelper.ModelToHashtable(para);
                    List<string> paraName = new List<string>();
                    string sqlTag = SqlInit(sql, out paraName);
                    IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
                    for (int i = 0; i < paraName.Count; i++)
                    {
                        string key = paraName[i];
                        object value = ht[key];
                        sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
                    }
                    var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
                    return result;
                }
                else if (para.GetType() == typeof(Hashtable))//Hashtanle入参
                {
                    Hashtable ht = (Hashtable)para;
                    List<string> paraName = new List<string>();
                    string sqlTag = SqlInit(sql, out paraName);
                    IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
                    for (int i = 0; i < paraName.Count; i++)
                    {
                        string key = paraName[i];
                        object value = ht[key];
                        sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
                    }
                    var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
                    return result;
                }
                else if (para.GetType() == typeof(object[]))
                {
                    List<string> paraName = new List<string>();
                    string sqlTag = SqlInit(sql, out paraName);
                    object[] ht = (object[])para;
                    IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
                    for (int i = 0; i < paraName.Count; i++)
                    {
                        string key = paraName[i];
                        object value = ht[i];
                        sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
                    }
                    var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
                    return result;
                }
                else//一个参数入参
                {
                    List<string> paraName = new List<string>();
                    string sqlTag = SqlInit(sql, out paraName);
                    IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
                    for (int i = 0; i < paraName.Count; i++)
                    {
                        string key = paraName[i];
                        object value = para;
                        sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
                    }
                    var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
                    return result;
                }
            } 
    复制代码

      3.4 查询语句

         如果是查询的话,执行完SQL返回一个DataTable,操作DataTable也太麻烦了吧,所以利用反射做了个实体转换器。

         DataTable转实体Model,DataRow转实体Model,DataTable转泛型T,DataRow转泛型T (之前的文章)

        

    复制代码
            public static T DataRowToModel<T>(DataRow row)
            {
                T model;
                Type type = typeof(T);
                ModelType modelType = GetModelType(type);
                switch (modelType)
                {
                    case ModelType.Struct://值类型
                        {
                            model = default(T);
                            if (row[0] != null)
                                model = (T)row[0];
                        }
                        break;
                    case ModelType.Enum://值类型
                        {
                            model = default(T);
                            if (row[0] != null)
                            {
                                Type fiType = row[0].GetType();
                                if (fiType == typeof(int))
                                {
                                    model = (T)row[0];
                                }
                                else if (fiType == typeof(string))
                                {
                                    var value = Enum.Parse(typeof(T), row[0].ToString());
                                    if (value != null)
                                        model = (T)value;
                                }
                            }
                        }
                        break;
                    case ModelType.String://引用类型 c#对string也当做值类型处理
                        {
                            model = default(T);
                            if (row[0] != null)
                                model = (T)row[0];
                        }
                        break;
                    case ModelType.Object://引用类型 直接返回第一行第一列的值
                        {
                            model = default(T);
                            if (row[0] != null)
                                model = (T)row[0];
                        }
                        break;
                    case ModelType.Else://引用类型
                        {
                            model = System.Activator.CreateInstance<T>();//引用类型 必须对泛型实例化
                            #region MyRegion
                            //获取model中的属性
                            BindingFlags flag = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                            PropertyInfo[] modelPropertyInfos = type.GetProperties(flag);
                            //遍历model每一个属性并赋值DataRow对应的列
                            foreach (PropertyInfo pi in modelPropertyInfos)
                            {
                                if (!pi.CanWrite) continue;
                                //获取属性名称
                                string tempName = GetFieldName(pi);
                                String name = string.IsNullOrEmpty(tempName) ? pi.Name : tempName;
                                if (row.Table.Columns.Contains(name) && row[name] != null)
                                {
                                    ModelType piType = GetModelType(pi.PropertyType);
                                    switch (piType)
                                    {
                                        case ModelType.Struct:
                                            {
                                                var value = Convert.ChangeType(row[name], pi.PropertyType);
                                                pi.SetValue(model, value, null);
                                            }
                                            break;
                                        case ModelType.Enum:
                                            {
                                                Type fiType = row[name].GetType();
                                                if (fiType == typeof(int))
                                                {
                                                    pi.SetValue(model, row[name], null);
                                                }
                                                else if (fiType == typeof(string))
                                                {
                                                    var value = Enum.Parse(typeof(T), row[name].ToString());
                                                    if (value != null)
                                                        pi.SetValue(model, (T)value, null);
                                                }
                                            }
                                            break;
                                        case ModelType.String:
                                            {
                                                var value = Convert.ChangeType(row[name], pi.PropertyType);
                                                pi.SetValue(model, value, null);
                                            }
                                            break;
                                        case ModelType.Object:
                                            {
                                                pi.SetValue(model, row[name], null);
                                            }
                                            break;
                                        case ModelType.Else:
                                            //throw new Exception("不支持该类型转换");
                                            break;
                                        default:
                                            throw new Exception("未知类型");
                                    }
                                }
                            }
                            #endregion
                        }
                        break;
                    default:
                        model = default(T);
                        break;
                }
    
                return model;
            }
    复制代码

    好了,差不多了吧,还有些多谢没讲,可以看我另外两篇博客。

    万能的SqlHelper,麻麻再也不用担心用什么数据库了

    DataTable转实体Model,DataRow转实体Model,DataTable转泛型T,DataRow转泛型T

    最后项目截图吧,稍后源码附上。

    源码下载:

     源码下载

    分类: WangSql
     
    http://www.cnblogs.com/deeround/p/5670891.html
  • 相关阅读:
    【已解决】github中git push origin master出错:error: failed to push some refs to
    好记心不如烂笔头,ssh登录 The authenticity of host 192.168.0.xxx can't be established. 的问题
    THINKPHP 5.0目录结构
    thinkphp5.0入口文件
    thinkphp5.0 生命周期
    thinkphp5.0 架构
    Django template
    Django queryset
    Django model
    Python unittest
  • 原文地址:https://www.cnblogs.com/webenh/p/5679896.html
Copyright © 2020-2023  润新知