zoukankan      html  css  js  c++  java
  • 二、手写ORM实现数据库插入

    在利用反射插入时会映射所有字段:但是插入时有主键自增不需要指定值
    因此利用特性标记主键,将主键排除掉
    1.编写属性
    [AttributeUsage(AttributeTargets.Property)]
        public class KeysAuthAtturbute : Attribute
        {
            public KeysAuthAtturbute() {}
        }
    2.标记属性
    3.查询除KeysAuthAtturbute之外的字段(排除主键)
      public static IEnumerable<PropertyInfo> PropertyInfoKeys(this Type type)
            {
                return type.GetProperties().Where(c => !c.IsDefined(typeof(KeysAuthAtturbute), true));
            }
    

      

    4.编写方法
    insert用到了参数化拼接,防止SQL注入
    例如:insert into Student
    values(@Age,@Birthday,@Sex) 再给赋值
      public  bool insert<T>(T t)
            {
                Type type = typeof(T);//获取到具体实体类型
                string TableName = type.Name;
                string fileName = string.Join(",",type.PropertyInfoKeys().Select(p=>string.Format("[{0}]", p.Name)));
                string valuesName = string.Join(",", type.PropertyInfoKeys().Select(p => $"@{p.Name}"));//将参数以@Age,@Sex方式列出
                string sql = $@"INSERT INTO [{TableName}] ({fileName}) VALUES ({valuesName})";
                SqlCommand cmd = new SqlCommand(sql, conn);
                //用于赋值参数  数据库允许为空的情况下,判断是否有值,没有的话赋值为空值
                IEnumerable<SqlParameter> parameters = type.PropertyInfoKeys().Select(p =>
                new SqlParameter($"@{p.Name}", p.GetValue(t)??DBNull.Value));
                cmd.Parameters.AddRange(parameters.ToArray());
                if (conn.State == System.Data.ConnectionState.Closed)
                {
                    conn.Open();
                }
                int result = cmd.ExecuteNonQuery();
                return result == 1;
            }
    5.调用
     sqlserverDBhelper sqlserverD = new sqlserverDBhelper();
                sqlserverD.insert<Student>( new Student {
                    Name = "lw",
                    Age = 20,
                    Birthday = DateTime.Now,
                    Sex = "女",
                });
     
    在程序中每次调用都需要拼接SQL字符串,使程序变得缓慢
    因此利用泛型缓存加载
     
    1.新建一个类 复制之前的代码,初始化构造函数里存放sql语句
     public class sqlhublider<T>
        {
            private static string selectsql = null;
            private static string insertsql = null;
            static sqlhublider()
            {
                Type type = typeof(T);//获取到具体类型
                string fileName = string.Join(",", type.PropertyInfoKeys().Select(p => string.Format("[{0}]", p.Name)));
                string valuesName = string.Join(",", type.PropertyInfoKeys().Select(p => $"@{p.Name}"));
                insertsql = $@"INSERT INTO [{type.Name}] ({fileName}) VALUES ({valuesName})";
     
                string filedstring = string.Join(",", type.GetProperties().Select(c => string.Format("[{0}]", c.Name)));
                selectsql = string.Format("select {0} from {1} where ID= ", filedstring, type.Name);
            }
     
            public static string Getsql(Sqltype sqltype)
            {
                switch (sqltype)
                {
                    case sqlserver.Sqltype.selectsql:
                        return selectsql;
                    case sqlserver.Sqltype.insertsql:
                        return insertsql;
                    default:
                        throw new Exception("sqltype");
                }
            }
        }
        public enum Sqltype//枚举类型 不同类型的的SQL语句
        {
            selectsql,
            insertsql
        }
    2.方法改编
     public  bool insert<T>(T t)
            {
                 Type type = typeof(T);//获取到具体类型
                 string sql= sqlhublider<T>.Getsql(Sqltype.insertsql);
                SqlCommand cmd = new SqlCommand(sql, conn);
                //用于赋值参数  数据库允许为空的情况下,判断是否有值,没有的话赋值为空值
                IEnumerable<SqlParameter> parameters = type.PropertyInfoKeys().Select(p =>
                new SqlParameter($"@{p.Name}", p.GetValue(t)??DBNull.Value));
                cmd.Parameters.AddRange(parameters.ToArray());
                if (conn.State == System.Data.ConnectionState.Closed)
                {
                    conn.Open();
                }
                int result = cmd.ExecuteNonQuery();
                return result == 1;
            }
    3.调用
     sqlserverDBhelper sqlserverD = new sqlserverDBhelper();
                sqlserverD.insert<Student>( new Student {
                    Name = "lw",
                    Age = 22,
                    Birthday = DateTime.Now,
                    Sex = "男",
                });
                sqlserverD.insert<Student>(new Student
                {
                    Name = "lw",
                    Age = 21,
                    Birthday = DateTime.Now,
                    Sex = "男",
                });
     
    调试时发现,第二次插入直接使用了之前的SQL语句,不需要再次拼装了,使性能得到了提升。
    泛型缓存原理:JIT会为不同的实体构造不同的类型副本
  • 相关阅读:
    属性的自动完成
    二十七、详测 Generics Collections TDictionary(3): TPairEnumerator、TKeyEnumerator、TValueEnumerator、ExtractPair
    Delphi 反转内存的函数
    类方法调用
    九、泛型排序器 TComparer
    十九、详测 Generics Collections TList (10): OnNotify 事件
    二十、详测 Generics Collections TList (11): Create
    二十一、详测 Generics Collections TQueue (1): Enqueue、Dequeue、Peek
    十四、详测 Generics Collections TList (5): Move、Exchange
    二十二、详测 Generics Collections TQueue (2): Create、Count、Clear、TrimExcess
  • 原文地址:https://www.cnblogs.com/cg-ww/p/13072520.html
Copyright © 2011-2022 走看看