标签:数据库 activator name cut fine 缓存 work prope turn
今天的内容对照上一节内容,上一节内容是对数据的查询,本节主要是对数据的新增。程序入口代码如下
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; }
因为我们现在做的是新增,数据库设计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)就可以判断一个类型是否具有某种特性。
由于在执行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语句的问题。
为了避免SQL注入问题的发生,我们通过参数化的方法拼装SQL执行语句,如下图所示:
在具体执行sql语句时,添加一下各个参数的值,如下图所示:
标签:数据库 activator name cut fine 缓存 work prope turn
原文地址:https://www.cnblogs.com/zxwDont/p/11473874.html