zoukankan      html  css  js  c++  java
  • ORM框架学习(二)

    ORM框架--新增数据

    今天的内容对照上一节内容,上一节内容是对数据的查询,本节主要是对数据的新增。程序入口代码如下

    static void Main(string[] args)
            {
                SqlHelper help = new SqlHelper();
                UserModel u1 = help.Query<UserModel>(1);
                Company com1 = help.Query<Company>(2);
                bool re1 = help.AddData(u1);
                bool re2 = help.AddData(com1);
            }

    AddData()方法和Query()方法一样。都是限制为where T:BaseModel的泛型方法。AddData代码如下所示

     public bool AddData<T>(T t) where T:BaseModel
            {
                bool re = true;
                
                try
                {
                    Type type=typeof(T);
                    string conStr = "Server=127.0.0.1;Database=master; integrated security=SSPI";
                    string AddStr = SqlBuilder<T>.GetSql(SqlBuilder<T>.SqlType.AddSql);
                    var sqlpara = type.GetProperties().FilterKey().Select(p => new SqlParameter("@" + p.GetMappingName(), p.GetValue(t) ?? DBNull.Value)).ToArray();
                    using (SqlConnection conn = new SqlConnection(conStr))
                    {
                        SqlCommand cmd = new SqlCommand(AddStr, conn);
                        cmd.Parameters.AddRange(sqlpara);
                        conn.Open();
                        int result= cmd.ExecuteNonQuery();
                        return result > 0;
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                    re = false;
                }
                return re;
            }

    1.按照特性过滤不需要实体字段

    因为我们现在做的是新增,数据库设计id为自增类型,所以在insert时,我们不需要新增id字段,所以就要想办法把id字段过滤。解决的办法是通过给ID设置特性ThemeKeyAttribute,特性定义如下所示

    /// <summary>
        /// 主键特性
        /// </summary>
        public class ThemeKeyAttribute:Attribute
        {
        
        }

    在特性方法里面没有任何实现,主要目的是用来做标记。同时,我们需要为id字段添加上面定义的特性,如下所示

    public class BaseModel
        {
            [ThemeKeyAttribute]
            public int Id { get; set; }
        }

    这样一来,就把company实体和User尸体的ID字段加上了特性。我们需要在获取实体属性时,调用过滤主键方法

    Filter是一个IEnumerable类型那个的扩展方法,定义如下所示:

    public static IEnumerable<PropertyInfo> FilterKey(this IEnumerable<PropertyInfo> props)
            {
                return props.Where(p=>!p.IsDefined(typeof(ThemeKeyAttribute),true));
            }

    在Filter方法中,直接传入当前的属性集合类型,把标记有ThemeKeyAttribute的属性过滤掉后再返回集合。

    在Filter方法中,我们通过方法p.IsDefined(typeof(ThemeKeyAttribute),true)就可以判断一个类型是否具有某种特性。

    2.泛型缓存

    由于在执行AddData()方法时,我们的sql语句结构都是类似的(insert into [tab]([]) values('')),为了提高代码执行效率,避免每次执行AddData()方法都去初始化一次sql语句,我们决定采用泛型缓存的方法,定义如下一个泛型类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Theme.Model;
    using Theme.Framework;
    namespace Theme.DAL
    {
        public  class SqlBuilder<T> where T:BaseModel
        {
            private static string FindSql=null;
            private static string AddSql=null;
            static SqlBuilder()
            {
                {
                    Type t = typeof(T);
                    string table = t.GetMappingName();
                    string props = string.Join(",", t.GetProperties().Select(p => "[" + p.GetMappingName() + "]"));
                    T ti = Activator.CreateInstance<T>();
                    FindSql = string.Format("select {0} from [{1}] where id=@id ", props, table);
                }
                {
                    Type type = typeof(T);
                    string table = type.GetMappingName();
                    string param = string.Join(",", type.GetProperties().FilterKey().Select(p => "[" + p.GetMappingName() + "]"));
                    string valueStr = string.Join(",", type.GetProperties().FilterKey().Select(p => "@" + p.GetMappingName()));
                    
                    //id为自增的关键字,不能插入,应该把ID屏蔽
                    AddSql = string.Format("insert into [{0}]({1}) values({2})", table, param, valueStr);
                }
            }
            public static string GetSql(SqlType sqltype)
            {
                switch (sqltype)
                {
                    case SqlType.AddSql:
                        return AddSql;
                    case SqlType.FindSql:
                        return FindSql;
                    default:
                        throw new Exception("wrong sqlType");
                }
            }
            public enum SqlType
            {
                FindSql,
                AddSql
            }
        }
    }

    注意,要通过限制当前类只能是继承了BaseModel父类的才能访问。我们把sql语句定义成静态字段,在每次使用该类之前,该类进行初始化生成FindSql和AddSql语句。这样确保了一个类型的对象只会初始化一次sql语句,这样就节省了多对象调用反复拼装sql语句的问题。

    3.参数化sql,避免sql注入

    为了避免SQL注入问题的发生,我们通过参数化的方法拼装SQL执行语句,如下图所示:

     在具体执行sql语句时,添加一下各个参数的值,如下图所示:

  • 相关阅读:
    poj 3693 Maximum repetition substring 重复次数最多的连续子串
    hdu 3518 Boring counting 后缀数组 height分组
    Codeforces 920G List Of Integers 二分 + 容斥
    Codeforces 920E Connected Components? 补图连通块个数
    Codeforces 920D Tanks
    LeetCode Weekly Contest 70 A B C D
    Educational Codeforces Round 37 A B C D E F
    检查站点SSL证书配置是否正确
    nginx rewrite之后post参数丢失问题
    Linux中如何避免buffers/cached占用过多内存
  • 原文地址:https://www.cnblogs.com/zxwDont/p/11473874.html
Copyright © 2011-2022 走看看