利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理

 
2018-3-10 15:18 | 发布:Admin | 分类:代码库 | 评论:0 | 浏览:45 |

该类在MVC中可以方便管理配置信息,可以直接把Model储存进数据库或者从数据库去除数据转为Model.

1 何为配置项目?

比如网站的名称,页脚信息,meta中的KeyWord信息等,如果不想硬编码到网页里,就需要使用配置文件进行储存,通常都是储存到数据库中.使用的时候读取出来,也方便修改.

2 MVC中对于数据的编辑一般是Model建模,然后View调用强类型,使用诸如@Html.TextBoxFor(m=>m.Name)之类的方式,取值时可以直接取到Model,不用再根据Request.From来一个一个的去赋值.

3 MVC的特性提供了强大的数据自检能力,如果Model中属性为Int类型,那么输入的时候如果不是数字则会直接提示类型错误.该特性支持正则表达式,可以说不用写一句js代码就可以完成数据的服务器端和客户端双重验证,十分强大.

4 本类只有两个方法,一个Load 一个Save,顾名思义,一个读取一个储存.参数都采用了泛型.你可以创建一个ConfigWebSIteModel基本设置类,

然后再创建一个ConfigSeo类,来分别管理不同的配置项目,可以一并储存到一个数据表中.

1
2
        T Load<T>();
        void Save<T>(T t);

不用的类中的属性不可以重复,否则会覆盖,比如ConfigWebSiteModel中有个ConfigWebSiteModel.Name 那么 ConfigSeo中就不能在出现Name属性,否则会覆盖掉,出错.

核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
    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
                        );
                }
            }
        }
    }
}

该类用到了两个外部类,一个是SqlHelper 就是普通的数据库辅助类,只用到了根据Sql语句和参数进行查询,更新,插入的功能,可以替换为自己的Helper类或者直接在此类中完成数据库操作

另外一个是把DataRow转换为Model对象的类,这个类是一个扩展方法,引用之后就可以直接对DataRows实例进行ToModel操作了.

1
return temp.Rows[0].ToModel<T>();

Sqlhelper类不再贴出,可以自己查找.扩展方法见本文:http://www.chengchenxu.com/Article/10/

本博客源码中也使用了此类,可以关注后期整理好源码后会开源,可以参考用法.

使用方法很简单:

1 这四个属性对应数据库中的表名以及列名,可以自定义,例如下图这样.

1
2
3
4
        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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ConfigSeoModel
{
        [Display(Name = "Meta关键字")]
        public string KeyWord { getset; }
        [Display(Name = "Meta描述")]
        public string Description { getset; }
}
 
//
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

 
Tags: Model MVC 泛型
 

利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理的更多相关文章

  1. winform中利用反射实现泛型数据访问对象基类(1)

    考虑到软件使用在客户端,同时想简化代码的实现,就写了一个泛型的数据访问对象基类,并不是特别健全,按道理应该参数化的方式实现insert和update,暂未使用参数化,抽时间改进. /// <su ...

  2. winform中利用反射实现泛型数据访问对象基类(3)

    继续完善了几点代码 满足没有主键的情况下使用 并且完善实体字段反射设置value时的类型转换 /// <summary> /// DAO基类 实体名必须要与数据表字段名一致 /// < ...

  3. winform中利用反射实现泛型数据访问对象基类(2)

    在1的基础上做了一点改进 参数化处理 看上去更简洁 无主键情况下 update 方法需要改进 insert delete没有问题  /// <summary>     /// DAO基类 ...

  4. C#利用反射和泛型给不同对象赋值

    /// <summary> /// 适用于初始化新实体 /// </summary> static public T RotationMapping<T, S>(S ...

  5. 利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model

    利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model   使用场景:网站配置项目,为了便于管理,网站有几个Model类来管理配置文件, 比如ConfigWebsiteMo ...

  6. DataTable转任意类型对象List数组-----工具通用类(利用反射和泛型)

    public class ConvertHelper<T> where T : new() { /// <summary> /// 利用反射和泛型 /// </summa ...

  7. 项目一:第五天 1、区域数据(pinyin4j-简码,城市编码) 2、Web层代码重构(model对象,分页代码提取) 3、区域分页查询 3、分区添加功能 4、定区管理管理-添加,分页

    Service: /** * @Description: 1.保存定区  2.让分区关联定区 * 对象三种状态 1.持久态(被session管理对象-一级缓存中有对象) 2.托管态(有OID标识,数据 ...

  8. 利用反射,泛型,静态方法快速获取表单值到Model

    在项目中经常需要处理表单,给model赋值,很烦人的一些重复代码.如下边的代码: News news = new News(); news.Id = int.Parse(Request.Form[&q ...

  9. 利用反射的特性将DataReader对象转化为List集合

    问题:将SqlDataReader对象转换为List<T>集合 思路: 1,利用反射的特性得到对应实体Model的公共属性 Type type = typeof(T); PropertyI ...

随机推荐

  1. 文件拷贝后无法编辑,用chown修改所有者和分组

    文件拷贝后无法编辑,chmod查看权限,发现当前用户不在文件里的所有者或所有组你,需用chwon修改拥有者和分组. 实例1:改变拥有者和群组 chown mail:mail log2012.log - ...

  2. background-position-x和background-position-y的兼容性问题

    一.语法: background-position-x : length | left | center | right background-position-y : length | left | ...

  3. LineageOS源码定制手机系统

    LineageOS源码定制手机系统 导语: 现在市场的手机基本就两种:  苹果机和android机. 今天我们不谈苹果机, 对小编我来讲,那是个奢侈品, android是我的最爱.对于一般androi ...

  4. 居然有这种操作?各路公司面试题(作者:马克-to-win)

    我喜欢考试,不考试,谁知道哪些掌握了哪些没有?? 面试什么的最有爱了(变态笑)~~~ http://www.mark-to-win.com/JavaBeginner/JavaBeginner4_web ...

  5. [NOIP2017] 时间复杂度 (模拟,栈)

    题目链接 Solution 用栈进行模拟. 记录一个 \(map\) 来看循环变量有没有用过. 对于每一次入栈都加信息. 出栈直接将 \(top\) 减一下. 反正一堆乱七八糟的东西瞎搞... 注意条 ...

  6. nvm、node、npm安装以及pycharm配置eslint

    nvm.node.npm之间的区别 1. nvm的官方叫法:nodejs版本管理工具. nvm相当于是家长,一个家长可以管理多个孩子. 也就是说:一个nvm可以管理很多node版本和npm版本. 2. ...

  7. Linq技巧2——限制返回数据中的继承类型

    假如有像下面这样的一个模型, 怎样在查询时仅仅需要的Cars呢? 这样的几个继承关系的实体中,查询时Where 条件可以加入OfType<SubType>(),你可以这样来写: var o ...

  8. 【kindeditor】KindEditor获取多个textarea文本框的值并判断非空

    kindeditor官网:http://kindeditor.net/demo.php 如何获取多个KindEditor中textarea文本框的值,方式很多种(带有HTML标签). var intr ...

  9. hdu 5438(类似拓扑排序)

    Ponds Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Sub ...

  10. LeetCode OJ——Word Break

    http://oj.leetcode.com/problems/word-break/ 动态规划题目,重点是建立出模型来: fun(start,end) = fun(start,i)*fun(i+1, ...