• 深入医生orm之insert细节


    这是第一次看一个组件的细节和内幕,好在医生的代码注释很多,堪称典范

    首先是看看生成的实体类

    因为医生宣称自己的orm没有使用反射,对此深感好奇,就看看是怎么插入数据和映射的

    生成的实体类代码如下

    using System;
    using PWMIS.Common;
    using PWMIS.DataMap.Entity;
    
    namespace SuperMarket 
    {
      [Serializable()]
      public partial class userinfo : EntityBase
      {
        public userinfo()
        {
                TableName = "userinfo";
                EntityMap=EntityMapType.Table;
                //IdentityName = "标识字段名";
        IdentityName="id";
    
                //PrimaryKeys.Add("主键字段名");
        PrimaryKeys.Add("id");
    
                
        }
    
    
          protected override void SetFieldNames()
          {
               PropertyNames = new string[] { "id","username","userpassword","userbrief","userimg" };
          }
    
    
    
          /// <summary>
          /// 
          /// </summary>
          public System.Int32 id
          {
              get{return getProperty<System.Int32>("id");}
              set{setProperty("id",value );}
          }
    
          /// <summary>
          /// 
          /// </summary>
          public System.String username
          {
              get{return getProperty<System.String>("username");}
              set{setProperty("username",value ,50);}
          }
    
          /// <summary>
          /// 
          /// </summary>
          public System.String userpassword
          {
              get{return getProperty<System.String>("userpassword");}
              set{setProperty("userpassword",value ,50);}
          }
    
          /// <summary>
          /// 
          /// </summary>
          public System.String userbrief
          {
              get{return getProperty<System.String>("userbrief");}
              set{setProperty("userbrief",value ,1073741823);}
          }
    
          /// <summary>
          /// 
          /// </summary>
          public System.String userimg
          {
              get{return getProperty<System.String>("userimg");}
              set{setProperty("userimg",value ,50);}
          }
    
    
      }
    }
     
    [Serializable()]
    首先这个实体类是可以序列化的,为以后的缓存做好了准备,不过这个效率不太高,实现可序列化接口就更好了
    userinfo : EntityBase
    实体类继承字同一个实体对象,基类应该是对象转换相关的

    TableName = "userinfo";

    这里指定了实体对应的表的名称,应该是生成sql预计时候用的,也为以后的分库分表横向拆分做好了准备
    EntityMap=EntityMapType.Table;

    protected override void SetFieldNames()
         {
              PropertyNames = new string[] { "id","username","userpassword","userbrief","userimg" };
         }

    这里保存了一个表所有的字段的名称

     

         /// <summary>
         ///
         /// </summary>
         public System.Int32 id
         {
             get{return getProperty<System.Int32>("id");}
             set{setProperty("id",value );}
         }

    这里是一个字段的属性,对这个属性进行读写时,并不是直接读写,而是调用基类的方法,进行存储

    实体类就这么多

    再调式看看

    调试上次插入的代码

                SuperMarket.userinfo objuserinfo = new SuperMarket.userinfo();
                EntityQuery<SuperMarket.userinfo> query = new EntityQuery<SuperMarket.userinfo>(objuserinfo,true);
                objuserinfo.username = "互联网fans";
                objuserinfo.userpassword = "1234567";
                objuserinfo.userimg = "http://tp2.sinaimg.cn/1271114553/180/5614484664/1";
                objuserinfo.userbrief = @"博客园菜鸟级博主,七脸阁主题APP开发者,专注于WebApp的开发和研究,
    提倡通过命题作文寻找创新的灵感和创意的点子。
    新浪应用搜索最新作品:表情帝。";
                //query.Save();
               // Response.Write(objuserinfo.id);
                int id= query.Insert(objuserinfo);
                Response.Write(id);

    先跟中一下赋值,医生的orm赋值有很多猫腻在里面,得看看

    objuserinfo.username = "互联网fans";

    跟进去后

    微博桌面截图_20121125114439

    进入赋值环节

    微博桌面截图_20121125114637

    赋值环节先根据表名称和字段名称生成了个key,然后存储了字段的长度,并比较了值的长度是否溢出,防止插入数据库时出错

    检查完成后开始赋值

    3

    这里不清楚是所有的属性默认都是null,还是因为我的表设计的默认值允许为null,下次在检验一下

    赋值时对PropertyNames属性列表进行遍历,找到赋值的属性就赋值,并在changedlist[i] 标记这个值已经变化了,为插入数据库时只插入赋值的字段做好了准备

    另外这里还注册了一个事件,虽然没弄明白注册这个时间是干嘛的有什么用,有没有性能风险,例如,web并发时候注册事件有没有影响,主要是不知道这个是干嘛的

    赋值到这里就完了,医生之所以没用使用映射,就是记录了表一共有那些字段,给那些字段赋值了,然后就可以插入了

    插入是个方法,医生没有放到实体类里面去而是新建了查询类

    EntityQuery<SuperMarket.userinfo> query = new EntityQuery<SuperMarket.userinfo>(objuserinfo,true);

    public EntityQuery(T entity,bool newEntity)
    {
         isNew = newEntity;
         init(entity);
    }

    private void init(T entity)
    {
        entity.PropertyGetting += new EventHandler<PropertyGettingEventArgs>(entity_PropertyGetting);
        entity.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(entity_PropertyChanged);
        currEntity = entity;
    }

    创建这个查询时也注册了不少事件,并指定了这个查询是那个实体类的查询,不清楚web应用程序频繁的注册事件对性能影响几何,哎

    跟入inser方法

    4

    在insert 方法中先判断了一下实体中字段的数量,然后指定了默认的数据库连接字符串

    在接下来

     private static int InsertInner(T entity, List<string> objFields, CommonDB DB)
            {
                if (objFields == null || objFields.Count == 0)
                    return 0;
    
                IDataParameter[] paras = new IDataParameter[objFields.Count];
                //CommonDB DB = MyDB.GetDBHelper();
    
    
                string sql = "INSERT INTO [" + entity.TableName+"]";
                string fields = "";
                string values = "";
                int index = 0;
    
                foreach (string field in objFields)
                {
                    if (entity.IdentityName != field)
                    {
                        fields += ",[" + field+"]";
                        string paraName = DB.GetParameterChar + "P" + index.ToString();
                        values += "," + paraName;
                        paras[index] = DB.GetParameter(paraName, entity.PropertyList(field));
                        //为字符串类型的参数指定长度 edit at 2012.4.23
                        if( paras[index].Value!=null && paras[index].Value.GetType()==typeof(string))
                        {
                            ((IDbDataParameter)paras[index]).Size = entity.GetStringFieldSize(field);
                        }
                        
                        index++;
                    }
                }
                sql = sql + "(" + fields.TrimStart(',') + ") VALUES (" + values.TrimStart(',') + ")";
    
                int count = 0;
    
                if (entity.IdentityName != "")
                {
                    //有自增字段
                    object id = entity.PropertyList(entity.IdentityName);
                    count = DB.ExecuteInsertQuery(sql, CommandType.Text, paras, ref id);
                    entity.setProperty(entity.IdentityName, Convert.ToInt32(id));
                }
                else
                {
                    count = DB.ExecuteNonQuery(sql, CommandType.Text, paras);
                }
                if (count > 0)
                    entity.ResetChanges();
    
                return count;
    
            }


     

    if (objFields == null || objFields.Count == 0)
        return 0;

    IDataParameter[] paras = new IDataParameter[objFields.Count];

    判断有没有字段,然后根据字段的数量创建参数列表

    string sql = "INSERT INTO [" + entity.TableName+"]";
               string fields = "";
               string values = "";
               int index = 0;

               foreach (string field in objFields)
               {
                   if (entity.IdentityName != field)
                   {
                       fields += ",[" + field+"]";
                       string paraName = DB.GetParameterChar + "P" + index.ToString();
                       values += "," + paraName;
                       paras[index] = DB.GetParameter(paraName, entity.PropertyList(field));
                       //为字符串类型的参数指定长度 edit at 2012.4.23
                       if( paras[index].Value!=null && paras[index].Value.GetType()==typeof(string))
                       {
                           ((IDbDataParameter)paras[index]).Size = entity.GetStringFieldSize(field);
                       }
                       index++;
                   }
               }
               sql = sql + "(" + fields.TrimStart(',') + ") VALUES (" + values.TrimStart(',') + ")";

    遍历字段 拼写sql并给sql参数赋值

    if (entity.IdentityName != "")
    {
        //有自增字段
        object id = entity.PropertyList(entity.IdentityName);
        count = DB.ExecuteInsertQuery(sql, CommandType.Text, paras, ref id);
        entity.setProperty(entity.IdentityName, Convert.ToInt32(id));
    }
    else
    {
        count = DB.ExecuteNonQuery(sql, CommandType.Text, paras);
    }

    在执行 sql语句时候,看有没有自增id,如果有自增id,执行时返回自增的id,没有的话就返回影响的行数

    感觉这里IdentityName 不太准确,自增id,主键,等等应该详细描述

    插入的就这么多

    剩下的就是调用sql帮助类了

    另外发现,orm默认没有实现读写分离,这点很不好。。。。。。。。。。。。。。。。。。

                        

     
  • 相关阅读:
    ZOJ 1001 A + B Problem
    献给那些心软的人!!
    将表格的数据插入另一个表格
    把链接 显示为方框
    【ibus】设置ibus输入法(pinyin & sunpinyin)
    [Mongo] How to Install Mongo on Debian(不要安装)
    [Sinatra、Mongo] Mongo
    Sinatra+SQLite3+DataMapper
    [sinatra] Sinatra再入门
    [slim] Slim
  • 原文地址:https://www.cnblogs.com/qqloving/p/2797021.html
Copyright © 2020-2023  润新知