使用场景:网站配置项目,为了便于管理,网站有几个Model类来管理配置文件,
比如ConfigWebsiteModel 用来管理基本信息
ConfigSeoModel 用来管理SEO信息
ConfigCacheModel 用来管理网站缓存信息
不用Model之间不能有重名属性字段
现在需要把他们储存到数据库中,并从数据库中读取出来转换成Model以便修改.不使用 List和Dictionary的原因是想利用MVC提供的强大数据自检能力.
核心类: 两个方法Load和Save Load传入T并返回T的实例 Save 传入T并储存到数据库
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Data;
- using System.Text;
- using ChengChenXu.Blog.Models;
- using System.Reflection;
- using System.Data.SqlClient;
- namespace ChengChenXu.Blog.DAL.SqlServer
- {
- public class ConfigModelDAL:IConfigModelDAL
- {
- private readonly string tableName = "blog_Config";//表名
- private readonly string columnKey = "c_Key";//key列名
- private readonly string columnValue = "c_Value";//Value列名
- private readonly string columnType = "c_Type";//Type列名
-
- /// <summary>
- /// 加载
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <returns></returns>
- public T Load<T>()
- {
- //通过sqlhelper获取datatable
- string sql = "select * from " + tableName;
- DataTable dt = SqlHelper.ExecuteDataTable(sql);
- //不存在记录
- if (dt.Rows.Count == 0) return default(T);
- //表行转换成列 ,临时表
- DataTable temp = new DataTable();
- foreach (DataRow dr in dt.Rows)
- {
- //添加一列,设置列的数据类型
- DataColumn dc = new DataColumn();
- dc.ColumnName = dr[columnKey].ToString();
- //根据字符串设置数据类型
- dc.DataType = System.Type.GetType(dr[columnType].ToString());
- temp.Columns.Add(dc);
- //如果时第一列,添加一行
- int index = temp.Columns.Count - 1;
- if (temp.Rows.Count == 0) temp.Rows.Add();
- //如果不是第一例,则行必定已经存在,直接赋值
- temp.Rows[0][index] = dr[columnValue];
- }
- if (temp.Columns.Count == 0) return default(T);
- //把临时表转换成Model并返回
- return temp.Rows[0].ToModel<T>();
- }
- /// <summary>
- /// 保存
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="t"></param>
- public void Save<T>(T t)
- {
- //利用反射获取对象所有属性
- string attributeName = String.Empty;
- PropertyInfo[] propertys = t.GetType().GetProperties();
- //获取数据库配置表放到内存中,对比数据是否已经存在
- DataTable dt = new DataTable();
- if (propertys.Length > 0)
- {
- dt = SqlHelper.ExecuteDataTable("select * from "+tableName+"");
- //给表设置主键,方便查找.
- dt.PrimaryKey=new[] {(dt.Columns[columnKey])};
- }
- //依次保存对象属性到数据库
- foreach (PropertyInfo pi in propertys)
- {
- //获取属性值
- var a = pi.GetValue(t, null);
- //值为NULL跳出,不保存,进入下个循环
- if (a == null)
- {
- SqlHelper.ExecuteNonQuery("delete from "+tableName+" where "+columnKey+" ='"+pi.Name+"' ");
- continue;
- }
- //准备sql参数
- SqlParameter[] parameters = SqlHelper.CreatParameters(
- new string[] { "Key", "Value" ,"Type"},
- new object[] { pi.Name, a, a.GetType().ToString() }
- );
- //查找属性是否已经存在于数据库中
- if(dt.Rows.Contains(pi.Name))
- {
- //存在 更新属性
- SqlHelper.ExecuteNonQuery(
- "update " + tableName + " set " + columnValue + " = @Value , " + columnType + " = @Type where " + columnKey + " = @Key",
- parameters
- );
- }
- else
- {
- //不存在 插入属性
- SqlHelper.ExecuteNonQuery(
- "insert into " + tableName + " (" + columnKey + "," + columnValue + "," + columnType + ") values (@key,@value,@type) ",
- parameters
- );
- }
- }
- }
- }
- }
复制代码
上面类中用到了一个DataTable的扩展类 用于扩展DataRow的ToModle方法 代码如下:
- /// <summary>
- /// 类 说 明:给DataTable和DataRow扩展方法,直接转换为对象集合或对象
- /// 编 码 人:程晨旭
- /// 联系方式:Email:97391519@qq.com
- /// Blog:http://chengchenxu.com
- /// 修改日期:2018-02-28
- /// 补充说明:此扩展类可以极大的简化操作,但是性能低下,大数据以及高性能要求下慎用.
- /// 此类如果放到asp.net的App_Code文件夹下会有编译错误,放到其他地方则无此问题
- /// </summary>
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Data;
- using System.Reflection;
- namespace ChengChenXu.Blog.DAL
- {
-
- internal static class DataTableExtensions
- {
- /// <summary>
- /// 把DataRow直接转换成对应的实体对象,给DataRow添加一个扩展方法,方便使用.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="dr"></param>
- /// <returns></returns>
- internal static T ToModel<T>(this DataRow dr)
- {
- T t = Activator.CreateInstance<T>();
- // 利用反射获得此模型的公共属性
- string attributeName = String.Empty;
- PropertyInfo[] propertys = t.GetType().GetProperties();
- foreach (PropertyInfo pi in propertys)
- {
- attributeName = pi.Name;
- // 检查DataTable是否包含此列
- //此处要求DataRow的列名称要和对象属性名称一致
- //注意:此处大小写不敏感
- if (dr.Table.Columns.Contains(attributeName))
- {
- // 判断此属性是否为只读(不包含set构造)
- if (!pi.CanWrite) { continue; }
- //给属性赋值
- var value = dr[attributeName];
- if (value != DBNull.Value)
- {
- pi.SetValue(t, value,null);
- }
- }
- }
- return t;
- }
- /// <summary>
- /// 将DataTable直接转化为对象集合
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="dt"></param>
- /// <returns></returns>
- internal static List<T> ToModelList<T>(this DataTable dt)
- {
- List<T> list = new List<T>();
- //调用ToModel方法添加List
- for (int i = 0; i < dt.Rows.Count; i++)
- {
- T t = Activator.CreateInstance<T>();
- t = dt.Rows[i].ToModel<T>();
- list.Add(t);
- }
- return list;
- }
- }
- }
复制代码
还用到了SqlHelper来进行数据库的操作,这个很简单,不在贴代码了.
使用方法:
1 这四个属性对应数据库中的表名以及列名,可以自定义,例如下图这样.
- private readonly string tableName = "blog_Config";//表名
- private readonly string columnKey = "c_Key";//key列名
- private readonly string columnValue = "c_Value";//Value列名
- private readonly string columnType = "c_Type";//Type列名
复制代码

key要设置为主键,类型都为varchar,长度视情况而定.
2 数据库链接字符串都是sqlHelper类中定义,SqlHelper类参考文章:http://www.chengchenxu.com/Article/11/sqlhelper
3 创建一个Model进行Load和Save操作
- public class ConfigSeoModel
- {
- [Display(Name = "Meta关键字")]
- public string KeyWord { get; set; }
- [Display(Name = "Meta描述")]
- public string Description { get; set; }
- }
-
- //
- ConfigModelDAL dal=new ConfigModelDAL();
-
- //new 一个Model
-
- ConfigSeoModel model=new ConfigSeoModel();
- model.KeyWord="关键字";
- model.Description = "描述"
-
- //完成保存
- dal.Save<ConfigSeoModel>(model);
-
-
- //读取
- ConfigSeoModel model = dal.Load<ConfigModel>();
复制代码
本文为博主原创,转载请保留出处: http://www.chengchenxu.com/Article/24/fanxing
|