C# 编写框架

今天在这里写一套简单的框架,主要用于一些小型的项目,用于数据的增删改查,通用分页查询等操作.所以功能并不强大,而且笔者也是新手,这里面也难免会有bug,忘读者朋友提醒.

现在我们进入正题吧,想要写一套通用的框架,反射是必须要熟知的.至少你需要知道如何通过反射获取属性和值.然后我们自定义一些特性,用于和数据库的连接.

完成框架的制作,我们分步骤来说

1.编写自定义特性

2.通过发射,拼接字符串,用于数据操作

3.完善框架

 

好,我们先编写自定义特性,创建2.0(因为2.0可以向上兼容,为了实现通用,习惯使用4.0的朋友们,辛苦你们一下了)类库,我的项目名称为ORMAttributes,创建完成之后,我们创建我们的特性,添加cs文件,取名为AttributeTF

这个类需要继承Attribute,首先我们创建特性BindTableAttribute,用于标识类与数据库表之间的关系

 1  /// <summary>
 2         /// 表特性
 3         /// </summary>
 4         /// 特性用于class类,一个类中使用只能出现一次
 5         /// 
 6         [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
 7         public class BindTableAttribute : Attribute
 8         {
 9             public BindTableAttribute()
10                 : base()
11             {
12 
13             }
14 
15             public BindTableAttribute(string name,Type t)
16             {
17                 _name = name;
18                 _ct = t;
19 
20                 new TabelInfo(name,t,ColAdd);
21             }
22 
23             private Type _ct;
24 
25             public Type Ct
26             {
27                 get { return _ct; }
28                 set { _ct = value; }
29             }
30 
31             private string _name = null;
32             public string name
33             {
34                 get { return _name; }
35             }
36 
37             private bool _colAdd = false;
38             public bool ColAdd
39             {
40                 get { return _colAdd; }
41                 set { _colAdd = value;
42                 ManageTabel._tabels[_name].ColAdd = value;
43                 }
44             }
45         }
View Code

_ct:使用记录当前这个类的实体(其实可以不使用,具体原因我后面会说到)

_name:记录名称,也就是用于对应的数据库表名称

_colAdd:是否自动添加列(这是一个辅助的功能,主要用于实体类添加字段后,对应的数据库中是否同样添加列)

接着我们创建BindFiledAttribute,用于标识属性与数据库表中列之间的关系

 1   /// <summary>
 2         /// 类特性
 3         /// </summary>
 4         /// 特性作用于属性/字段上.且只能出现一次
 5         [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
 6         public class BindFiledAttribute : Attribute
 7         {
 8             public BindFiledAttribute()
 9                 : base()
10             {
11 
12             }
13 
14             public BindFiledAttribute(string name)
15             {
16                 _strName = name;
17             }
18 
19             private string _strName = null;
20 
21             public string StrName
22             {
23                 get { return _strName; }
24             }
25 
26 
27             private string _type = null;
28 
29             public string Type
30             {
31                 get { return _type; }
32                 set { _type = value; }
33             }
34 
35             private string _readFormat = null;
36 
37             public string ReadFormat
38             {
39                 get { return _readFormat; }
40                 set { _readFormat = value; }
41             }
42 
43             private string _writeFormat = null;
44 
45             public string WriteFormat
46             {
47                 get { return _writeFormat; }
48                 set { _writeFormat = value; }
49             }
50 
51             private int _index = -1;
52 
53             public int Index
54             {
55                 get { return _index; }
56                 set { _index = value; }
57             }
58 
59             private bool _isKey = false;
60 
61             public bool IsKey
62             {
63                 get { return _isKey; }
64                 set { _isKey = value;
65                 }
66             }
67 
68             private bool _isIdentity = false;
69 
70             public bool IsIdentity
71             {
72                 get { return _isIdentity; }
73                 set { _isIdentity = value; }
74             }
75 
76         }
View Code

_strName:表示列的名称

_type:数据类型,例如:varchar(100)...

_readFormat:读取时样式(这个不用在意,笔者发现,这个完全可以返回由程序员自己完成,意义不大)

_writeFormat:保存时样式(同上)

_index:序列号,新增时比较实用,同样可以提高效率(笔者解决了新增时顺序的问题,后面有详细介绍)

_isKey:是否是主键列

is_IsIdentity:是否为自动增涨列

ok,,这样我们的自定义特性也就完成了,,下面我们在model层的实体类上标识下我们所写的特性吧

 1 [BindTableAttribute("MyFromWork", typeof(MyFromWork), ColAdd = true)]
 2     public class MyFromWork {
 3         private int _id;
 4         [BindFiledAttribute("id",IsIdentity=true, IsKey = true, Type = "int")]
 5         public int Id
 6         {
 7             get { return _id; }
 8             set { _id = value; }
 9         }
10         
11         private string _name;
12         [BindFiledAttribute("name", Type = "varchar(50)")]
13         public string Name
14         {
15             get { return _name; }
16             set { _name = value; }
17         }
18 
19         private string _author;
20 
21         [BindFiledAttribute("author", Type = "varchar(50)")]
22         public string Author
23         {
24             get { return _author; }
25             set { _author = value; }
26         }
27 
28         private string _remarks;
29         [BindFiledAttribute("remarks", Type = "nvarchar(500)")]
30         public string Remarks
31         {
32             get { return _remarks; }
33             set { _remarks = value; }
34         }
View Code

怎么样,是不是很轻松呢,好,我们继续向下说

特性已经出现了,那么我们必定需要有一个地方来存储我们所标识的实体对应的值,所以笔者在这定义了TabelInfo和FileInfo,分别来记录BindTableAttribute和BindFiledAttribute.

  public class FileInfo
    {
        public FileInfo() : base() { }

        /// <summary>
        /// 字段名
        /// </summary>
        private string _strName;

        public string StrName
        {
            get { return _strName; }
            set { _strName = value; }
        }

        /// <summary>
        /// 数据类型(数据库中)
        /// </summary>
        private string _type;

        public string Type
        {
            get { return _type; }
            set { _type = value; }
        }

        /// <summary>
        /// 展现时字符串样式
        /// </summary>
        private string _readFormat;

        public string ReadFormat
        {
            get { return _readFormat; }
            set { _readFormat = value; }
        }

        /// <summary>
        /// 保存时字符格式
        /// </summary>
        private string _writeFormat;

        public string WriteFormat
        {
            get { return _writeFormat; }
            set { _writeFormat = value; }
        }

        /// <summary>
        /// 序列号
        /// </summary>
        private int _index=-1;

        public int Index
        {
            get { return _index; }
            set { _index = value; }
        }

        /// <summary>
        /// 是否作为条件使用
        /// </summary>
        private bool _isKey;

        public bool IsKey
        {
            get { return _isKey; }
            set { _isKey = value; }
        }

        /// <summary>
        /// 是否为自动增涨列
        /// </summary>
        private bool _isIdentity;

        public bool IsIdentity
        {
            get { return _isIdentity; }
            set { _isIdentity = value; }
        }
View Code
  public class TabelInfo
    {   #region 属性
        //表名
        private string _tabelName;

        public string TabelName
        {
            get { return _tabelName; }
            set { _tabelName = value; }
        }

        private Type _type;

        public Type TabelType
        {
            get { return _type; }
            set { _type = value; }
        }

        /// <summary>
        /// 字段特性
        /// </summary>
        private ArrayList _propretys;

        public ArrayList Propretys
        {
            get { return _propretys; }
            set { _propretys = value; }
        }

        private bool _colAdd = false;
        public bool ColAdd
        {
            get { return _colAdd; }
            set { _colAdd = value; }
        }

        #endregion
    }

因为笔者希望这些实体类在使用的同时就被记录下来,并被缓存下来,所以笔者有创建了ManageTabel类,用于缓存已被记录的实体类,以及初始化时获取特性等操作

 public static class ManageTabel
    {
        /// <summary>
        /// 用于缓存数据
        /// </summary>
        public static IDictionary<string, TabelInfo> _tabels=new Dictionary<string,TabelInfo>();

        public static bool IsHave(string key) {
            return _tabels.ContainsKey(key);
        }

        /// <summary>
        /// 初始化数据
        /// </summary>
        public static void Intital() {
            foreach (string key in _tabels.Keys)
            {
                TabelInfo ti = _tabels[key];
                if (ti.Propretys == null)
                {
                    //获取当前类中的公开属性
                    PropertyInfo[] pinfo = ti.TabelType.GetProperties();

                    foreach (PropertyInfo item in pinfo)
                    {
                        object[] attributes = item.GetCustomAttributes(typeof(BindFiledAttribute),false);
                        for (int i = 0; i < attributes.Length; i++)
                        {
                            //获取对应属性值
                            FileInfo fi = new FileInfo();
                            BindFiledAttribute ba = attributes[i] as BindFiledAttribute;
                            if(ba!=null)
                            {
                                fi.StrName = ba.StrName;
                                fi.Type = ba.Type;
                                fi.ReadFormat = ba.ReadFormat;
                                fi.WriteFormat = ba.WriteFormat;
                                fi.Index = i;
                                fi.IsIdentity = ba.IsIdentity;
                                fi.IsKey = ba.IsKey;
                            }
                            if (ti.Propretys == null)
                                ti.Propretys = new System.Collections.ArrayList();
                            ti.Propretys.Add(fi);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 重置
        /// </summary>
        public static void Result() {
            _tabels.Clear();
        }

        /// <summary>
        /// 添加数据到集合
        /// </summary>
        /// <param name="key">唯一标识列</param>
        /// <param name="ti">对象数据</param>
        /// <returns></returns>
        public static bool AddObject(string key, TabelInfo ti) {
            if (IsHave(key))
            {
                throw new Exception("当前数据已存在");
            }

            _tabels.Add(key,ti);
            return true;
        }

        /// <summary>
        /// 修改数据集
        /// </summary>
        /// <param name="key"></param>
        /// <param name="ti"></param>
        /// <returns></returns>
        public static bool EditeObject(string key, TabelInfo ti) {
            if (IsHave(key))
            {
                _tabels[key] = ti;
                return true;
            }
            throw new Exception("没有找到您想要替换的数据集");
        }

        /// <summary>
        /// 删除数据集
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool RemoveObject(string key) {
            if (IsHave(key))
            {
                _tabels.Remove(key);
                return true;
            }
            throw new Exception("没有找到您想要删除的数据集"); 
        }
    }
View Code

_tabels用于缓存数据使用,这里的方法和属性都是静态的,就是方便用户随时使用

好了,我们现在回到之前的TabelInfo类,这个类中,我们需要添加一个带参构造

 public TabelInfo(string name,Type t,bool colAdd) {
            _tabelName = name;
            _type = t;
            _colAdd = colAdd;
            if (!ManageTabel.IsHave(name))
            {
                ManageTabel.AddObject(name, this);
                ManageTabel.Intital();
            }
        }
View Code

这里主要是让他起到自动缓存和读取的作用,不至于我们忘记缓存等操作而增加操作

好,现在我们的第一步工作算是完成了,我们进入第二步工作,数据库的连接和数据库操作等

这里我们可以重新创建类库DBUitily.也可以继续在该类库下添加类,笔者比较喜欢分开写所以创建了类库

类库中我们创建类DBSqlServer类,该类主要针对sqlserver而编写的.因为笔者对其他数据库并不是很了解,这里就没有过多的去写了,读者可以自行改写.

这里先写关于数据库的连接字符串,笔者习惯从配置文件中读取该字符串,这里依然从配置文件中读取

private static string CONNECTION = ConfigurationManager.AppSettings["connection"].ToString();

现在编写关于数据库连接操作的一些基本操作

  #region 数据库执行
        /// <summary>
        /// 执行新增,删除,修改等语句
        /// </summary>
        /// <param name="txt"></param>
        /// <returns></returns>
        public static int ExecuteSql(string txt, CommandType cmdType, params SqlParameter[] paras)
        {
            int count = 0;
            using (SqlConnection conn = new SqlConnection(CONNECTION))
            {
                lock (conn)
                {
                    try
                    {
                        SqlCommand cmd = new SqlCommand();
                        CommondPar(conn, cmd, txt, cmdType, null, paras);
                        count = cmd.ExecuteNonQuery();
                    }
                    catch (Exception)
                    {
                        count = -1;
                    }
                    finally
                    {
                        if (conn.State == ConnectionState.Open)
                        {
                            conn.Close();
                            conn.Dispose();
                        }
                    }
                }
                return count;
            }
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="cmdType"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public static DataSet ExecuteDataRead(string txt, CommandType cmdType, params SqlParameter[] paras)
        {
            DataSet ds = new DataSet();
            using (SqlConnection conn = new SqlConnection(CONNECTION))
            {
                lock (conn)
                {
                    try
                    {
                        SqlCommand cmd = new SqlCommand();
                        CommondPar(conn, cmd, txt, cmdType, null, paras);
                        using (SqlDataAdapter da = new SqlDataAdapter(txt, conn))
                        {
                            da.SelectCommand = cmd;
                            da.Fill(ds);
                        }
                    }
                    catch (Exception)
                    {
                        ds = null;
                    }
                    finally
                    {

                        if (conn.State == ConnectionState.Open)
                        {
                            conn.Close();
                            conn.Dispose();
                        }
                    }
                }
                return ds;
            }
        }

        /// <summary>
        /// 公用方法
        /// </summary>
        /// <param name="conn">数据库连接</param>
        /// <param name="cmd">SqlCommand</param>
        /// <param name="text">sql语句或者存储过程名称</param>
        /// <param name="cmdType"></param>
        /// <param name="trans"></param>
        /// <param name="paras"></param>
        private static void CommondPar(SqlConnection conn, SqlCommand cmd, string text, CommandType cmdType, SqlTransaction trans, params SqlParameter[] paras)
        {
            if (conn == null || cmd == null)
                throw new Exception("缺少必要参数S去了Connection或者SqlCommand");
            else
            {
                if (conn.State != ConnectionState.Open)
                {
                    conn.Open();
                }
                cmd.CommandText = text;
                cmd.CommandType = cmdType;
                cmd.Connection = conn;
                if (trans != null)
                    cmd.Transaction = trans;
                if (paras != null)
                    cmd.Parameters.AddRange(paras);
            }
        }
        #endregion
View Code

如此,我们便可以写创建表和列的字符串了

    /// <summary>
        /// 创建表
        /// </summary>
        /// <param name="ti">数据源</param>
        /// <returns></returns>
        private static bool CreateTabel(TabelInfo ti)
        {
            StringBuilder sql = new StringBuilder();
            sql.AppendLine("CREATE TABLE [" + ti.TabelName + "](");
            sql.AppendLine(AddColumns(ti,null,false));
            sql.AppendLine(")");
            return ExecuteSql(sql.ToString(),CommandType.Text,null)>0?true:false;
        }

        /// <summary>
        /// 添加列
        /// </summary>
        /// <param name="ti">数据源</param>
        /// <returns></returns>
        private static string AddColumns(TabelInfo ti, ArrayList list, bool isHave)
        {
            StringBuilder sql = new StringBuilder();
            int index = 0;
            //是否是已存在的表
            if (isHave)
            {
                sql.AppendLine("ALTER TABLE ["+ti.TabelName +"] ADD");
                foreach (FileInfo item in ti.Propretys)
                {
                    if (list.Contains(item.StrName)) {
                        continue;
                    }
                    if (index != 0)
                        sql.AppendLine(",");
                    index++;
                    sql.AppendLine(" [" + item.StrName + "] " + item.Type);
                }
                return sql.ToString();
            }

            //表不存在的情况下
            
            bool isKey = true;  //主键是否存在,true未出现,false已出现
            foreach (FileInfo item in ti.Propretys)
            {
                if (index > 0)
                    sql.AppendLine(",");
                index++;
                //拼接字符串
                sql.AppendLine(" [" + item.StrName + "] " + item.Type);
                if (item.IsIdentity)
                    sql.AppendLine(" IDENTITY(1,1) ");
                if (item.IsKey)
                    if (isKey)
                    { sql.AppendLine(" PRIMARY KEY "); isKey = false; }
            }
            return sql.ToString();
        }
View Code

这里,我们需要注意一点小细节

1.表名和列名,我们需要使用"[]"符号括住,防止关键字的出现

2.主键列和自动增涨列的一些标识

因为笔者考虑到,可能有些程序已经存在表了,所以需要创建前要判断下是否存在或者是列是否已存在

  /// <summary>
        /// 检查是否存在表
        /// </summary>
        /// <param name="ti">数据源</param>
        /// <returns></returns>
        private static bool IsHaveTabel(TabelInfo ti)
        {
            if (ti == null)
            {
                throw new Exception("数据源不能为空!");
            }

            StringBuilder sql = new StringBuilder();
            sql.AppendLine("SELECT COUNT(name) FROM SYSOBJECTS WHERE XTYPE='U' AND NAME='" + ti.TabelName + "'");
            DataSet ds = ExecuteDataRead(sql.ToString(), CommandType.Text);
            if (ds != null)
                if (ds.Tables.Count > 0)
                    if (ds.Tables[0].Rows.Count > 0)
                    {
                        //查看数据是否存在
                        if (Convert.ToInt32(ds.Tables[0].Rows[0][0]) > 0)
                            //存在
                            return true;
                    }

            return false;
        }


        /// <summary>
        /// 检查列
        /// </summary>
        /// <param name="ti">数据源</param>
        /// <returns></returns>
        private static ArrayList IsHaveCol(TabelInfo ti)
        {
            StringBuilder sql = new StringBuilder();
            sql.AppendLine("SELECT name FROM SYSCOLUMNS WHERE ID=OBJECT_ID('" + ti.TabelName + "')");
            DataSet ds = ExecuteDataRead(sql.ToString(), CommandType.Text, null);
            if (ds != null)
                if (ds.Tables.Count > 0)
                    if (ds.Tables[0].Rows.Count > 0)
                    {
                        //存在
                        ArrayList list = new ArrayList();
                        foreach (DataRow row in ds.Tables[0].Rows)
                        {
                            list.Add(row[0].ToString());
                        }
                        return list;
                    }
            return null;
        }

ok..这里就已经差不多了,下面,我们需要考虑用户的需求了,可能该用户数据库中已经存在了表,所以不希望框架还重新连接数据库判断是否存在表,这样毕竟还是会消耗资源的,发布后也不希望有这样的操作的.所以笔者在这里创建了一个状态,用于标识

private static bool _ISCREATE;

        public static bool ISCREATE
        {
            get {
                try
                {
                    _ISCREATE = ConfigurationManager.AppSettings["auto"].ToString().Equals("1");
                }
                catch (Exception)
                {
                    _ISCREATE = true;
                }
                return DBSqlServer._ISCREATE; }
        }

同样是从配置文件中读取,如果不存在这样的auto(自动化)节点,则默认自动创建

好,下面就正事创建表的操作了

 public static bool CreateTable<T>(Type t,ref TabelInfo ti)
        {
            //通过类型,获取名称,从缓存中读取
            //隐式创建缓存
            object[] obj = t.GetCustomAttributes(typeof(BindTableAttribute), false);
            foreach (BindTableAttribute item in obj)
            {
                if (item == null)
                    continue;
                string key = item.name;
                ti = ManageTabel._tabels[key] == null ? ti : ManageTabel._tabels[key];
            }
            if (ti == null)
            {
                throw new Exception("数据结构发生异常");
            }

            if (!ISCREATE)
                return true;

            //检查数据库中是否存在
            if (IsHaveTabel(ti))
            {
                //检查是否存在新的字段需要添加
                if (!ti.ColAdd)
                    return false;
                ArrayList list = IsHaveCol(ti);
                if (list.Count > 0 && list.Count < ti.Propretys.Count)
                {
                    //添加列
                    string sql = AddColumns(ti, list, true);
                    return ExecuteSql(sql, CommandType.Text,null)>0?true:false;
                }
                return false;
            }
            return CreateTabel(ti);
        }
View Code

这里有这样的一句话

 if (!ti.ColAdd) return false;

没错了,这个就是我们之前特性中定义的数据,是否自动添加列,这个作用就是在这里了,如果用户自动添加列,这里会判断用户是否有新增的字段,从而添加到数据库,这里这样的操作,就会避免很多不必要的操作了

这个类算是完成了,因为要自动化的通用增删改查等操作,所以我们还需要一个数据库业务逻辑类,笔者命名为:DBManage

这里的操作主要分为5类,新增,删除,修改,查询,分页;

笔者先说删除与修改;

删除;我们需要的参数有表名,主键列(也就是删除条件)

  private bool Delete(string strWhere)
        {
            StringBuilder sql = new StringBuilder();

            try
            {
                sql.AppendLine("DELETE [" + ti.TabelName + "] ");
                if (string.IsNullOrEmpty(strWhere))
                {
                    //条件为空
                    foreach (PropertyInfo item in ti.TabelType.GetProperties())
                    {
                        //获取特性,再次验证
                        object[] objs = item.GetCustomAttributes(typeof(BindFiledAttribute), false);

                        bool fast = true;
                        foreach (BindFiledAttribute bfa in objs)
                        {
                            if (bfa.IsKey)
                            {
                                if (fast)
                                {
                                    sql.AppendLine(" WHERE ");
                                    fast = false;
                                }
                                sql.AppendLine(" [" + bfa.StrName + "]='" + item.GetValue(model, null) + "'");
                            }

                        }
                    }
                    return DBSqlServer.ExecuteSql(sql.ToString(), System.Data.CommandType.Text, null) > 0 ? true : false;
                }
                else
                {
                    //按条件查询
                    sql.AppendLine(" WHERE " + strWhere);
                    return DBSqlServer.ExecuteSql(sql.ToString(), System.Data.CommandType.Text, null) > 0 ? true : false;
                }

            }
            catch (Exception)
            {
                return false;
            }
        }

这里,参数中我添加了一个条件,这个条件重要是笔者担心业务中有全部删除这一项操作,可能有些人觉得没有这样的必要,但是笔者觉得这样的业务还是可能会出现的,所以留了下来

细心的读者一定会发现,这里有一个主要参数ti,但是却没有看到声明的标记,这里笔者解释下,ti其实是TableInfo的实体对象,因为所有操作都需要,所以笔者已经将其定义为全局变量,方便使用,具体如何实现的,我后面会介绍到,请不要着急,现在只要知道它是TableInfo就可以了

下面我们说说修改,修改与删除几近相同

private bool Edite(string strWhere)
        {
            StringBuilder sql = new StringBuilder();
            //修改数据,1.是否有自定义条件
            if (string.IsNullOrEmpty(strWhere))
            {
                //根据主键修改
                sql.AppendLine("UPDATE [" + ti.TabelName + "] SET ");
                bool fast = true;
                foreach (PropertyInfo item in ti.TabelType.GetProperties())
                {
                    //获取特性,再次验证
                    object[] objs = item.GetCustomAttributes(typeof(BindFiledAttribute), false);


                    foreach (BindFiledAttribute bfa in objs)
                    {
                        if (bfa.IsKey || bfa.IsIdentity)
                        {
                            strWhere += "["+bfa.StrName + "]='" + item.GetValue(model, null) + "'";
                            continue;
                        }
                        if (!fast)
                            sql.AppendLine(",");
                        fast = false;
                        sql.AppendLine("[" + bfa.StrName + "]='" + item.GetValue(model, null) + "' ");
                    }
                }
                return DBSqlServer.ExecuteSql(sql.ToString() + " where " + strWhere, System.Data.CommandType.Text, null) > 0 ? true : false;

            }

            return false;
        }
View Code

这里有个标点的问题,因为是循环加入列的,列与列之间有逗号","相隔,笔者之前看到很多程序员喜欢加完符号后,再循环结束截取字符串,笔者不建议这样的操作,虽然语法不难,但笔者并不喜欢.所以笔者使用了这样的方式,在语句前面加上符号,并第一次不加入.

其他的就是拼接字符串了

下面我们说说新增吧,这里有个先后顺序问题

先上代码吧

   #region 新增
        private bool Add()
        {
            StringBuilder sql = new StringBuilder();
            sql.AppendLine("INSERT INTO [" + ti.TabelName + "](");
            bool index = false;
            bool index2 = false;
            StringBuilder value = new StringBuilder();
            foreach (PropertyInfo item in ti.TabelType.GetProperties())
            {
                //获取特性,再次验证
                bool again = false;
                object[] objs = item.GetCustomAttributes(typeof(BindFiledAttribute), false);

                foreach (BindFiledAttribute bfa in objs)
                {
                   
                    if (bfa.IsIdentity)
                        again = true;

                    if (bfa.IsIdentity)
                        continue;
                    if (index)
                        sql.AppendLine(",");
                    index = true;
                    sql.AppendLine(" [" + bfa.StrName+"]");
                }

                if (again)
                    continue;
                if (index2)
                    value.AppendLine(",");
                index2 = true;
                value.AppendLine("'" + item.GetValue(model, null) + "'");
            }
            sql.AppendLine(") VALUES (");
            sql.AppendLine("" + value.ToString());
            sql.AppendLine(")");
            return DBSqlServer.ExecuteSql(sql.ToString(), System.Data.CommandType.Text, null)>0;
        }
        #endregion

这里我们需要两个字符串,一个用于拼接字符串,还有一个就是拼接值.在拼接列名时,直接记录下插入值,这样就不用考虑顺序的问题了,ok,下面还有一个小细节的问题,这个想必心细的读者已经发现了,那就是插入列时,我们需要判断该列是否是自动增涨列,如果是,则过滤这次操作,直接进入下一次操作

T_T...说起来好简单啊,笔者可是花了两天时间才完成呢!!!T_T

不抱怨了,下面是查询了,这个不算难,直接上代码了

/// <summary>
        /// 普通查询
        /// </summary>
        /// <param name="strWhere">条件</param>
        /// <returns></returns>
        private DataSet Select(string strWhere)
        {
            StringBuilder sql = new StringBuilder();
            sql.AppendLine("SELECT ");
            bool fast = true;
            foreach (FileInfo fi in ti.Propretys)
            {
                if (!fast)
                    sql.AppendLine(",");
                fast = false;
                sql.AppendLine("["+fi.StrName+"]");
            }
            fast = true;
            sql.AppendLine(" FROM [" + ti.TabelName + "] ");
            if (!string.IsNullOrEmpty(strWhere))
            {
                sql.AppendLine("WHERE " + strWhere);
            }
            return DBSqlServer.ExecuteDataRead(sql.ToString(), CommandType.Text, null);
        }

这里有条件查询,也可以查询所有,你们懂得,笔者还是担心那些问题,,呵呵

笔者主要是想说分页的问题,这个分页笔者并不是很喜欢,因为还不算完善,之后笔者会去完善这一块的东西,希望大家理解

 /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="index">当前页</param>
        /// <param name="size">每页数据量</param>
        /// <param name="strWhere">条件</param>
        /// <param name="order">排序字段</param>
        /// <param name="desc">是否倒序</param>
        /// <returns></returns>
        private DataSet Select(int? index, int? size, string strWhere, string order, bool desc)
        {
            StringBuilder sql = new StringBuilder();
            if (size <= 0 || index < 0)
                throw new Exception("超出参数表示范围.参数不可以小于0");

            sql.AppendLine("select top " + size + " ");

            bool fast = true;
            string key = "";
            foreach (FileInfo fi in ti.Propretys)
            {
                if (!fast)
                    sql.AppendLine(",");
                fast = false;

                sql.AppendLine(" ["+fi.StrName+"]");
                if (fi.IsKey)
                    key = fi.StrName;
            }
            sql.AppendLine(" FROM ["+ti.TabelName+"] WHERE ["+key+"] NOT IN(");

            sql.AppendLine("select top " + (size * (index - 1)) + " ["+key+"] FROM ["+ti.TabelName+"]");

            if (!string.IsNullOrEmpty(strWhere))
                sql.AppendLine(" WHERE "+strWhere);
            if(!string.IsNullOrEmpty(order))
                sql.AppendLine(" ORDER BY [" + order + "] " + (desc ? "DESC" : "ASC"));
            sql.AppendLine(")");
            return DBSqlServer.ExecuteDataRead(sql.ToString(), CommandType.Text, null);
        }

        #endregion

这里主要是通过两个top来完成分页的,笔者之所以说不完善,是因为,在数据量超大的时候,这个会很耗效率,这个具体的,笔者会改善,因为时间比较紧,所以望读者们理解

下面就是这个类的完整代码

   public class DBManage<T>
    {
        public DataSet ds_model = null;
        T model;
        public DBManage(T t)
        {
            model = t;

            FlagTabel(t.GetType());

        }

        private Type t = null;

        private string GetSql()
        {
            return string.Empty;
        }

        #region 数据库操作分支入口
        private TabelInfo ti = null;
        private void FlagTabel(Type t)
        {
            this.t = t;
            DBSqlServer.CreateTable<Type>(t, ref ti);
        }

        #region 数据库公开类
        /// <summary>
        /// 公开数据操作
        /// </summary>
        /// <param name="txt">sql</param>
        /// <param name="cmdType">操作类型</param>
        /// <param name="paras">参数列</param>
        /// <returns></returns>
        public static int ExecuteSql(string txt, CommandType cmdType, params SqlParameter[] paras)
        {
            return DBSqlServer.ExecuteSql(txt, cmdType, paras);
        }
        /// <summary>
        /// 公开数据操作
        /// </summary>
        /// <param name="txt">sql</param>
        /// <param name="cmdType">操作类型</param>
        /// <param name="paras">参数列</param>
        /// <returns></returns>
        public static DataSet ExecuteDataSet(string txt, CommandType cmdType, params SqlParameter[] paras)
        {
            return DBSqlServer.ExecuteDataRead(txt, cmdType, paras);
        }
        #endregion

        /// <summary>
        /// 操作类
        /// </summary>
        /// <typeparam name="T">需要操作的类</typeparam>
        /// <param name="t">需要操作的实体类</param>
        /// <param name="type">操作类型</param>
        public bool ManageModel(ModelState type)
        {
            return ResultManage(type, null, null, null, null, false);
        }

        /// <summary>
        /// 操作类
        /// </summary>
        /// <typeparam name="T">需要操作的类</typeparam>
        /// <param name="t">需要操作的实体类</param>
        /// <param name="type">操作类型</param>
        /// <param name="index">当前页(用于分页查询)</param>
        /// <param name="size">每页条数(用于分页查询)</param>
        public bool ManageModel(ModelState type, int index, int size)
        {
            return ResultManage(type, index, size, null, null, false);
        }

        /// <summary>
        /// 操作类
        /// </summary>
        /// <typeparam name="T">需要操作的类</typeparam>
        /// <param name="t">需要操作的实体类</param>
        /// <param name="type">操作类型</param>
        /// <param name="obj">多条件</param>
        public bool ManageModel(ModelState type, object[] obj)
        {
            return ResultManage(type, null, null, null,  null, false,obj);
        }

        /// <summary>
        /// 操作类
        /// </summary>
        /// <typeparam name="T">需要操作的类</typeparam>
        /// <param name="t">需要操作的实体类</param>
        /// <param name="type">操作类型</param>
        /// <param name="strWhere">单个条件</param>
        public bool ManageModel(ModelState type, string strWhere)
        {
            return ResultManage(type, null, null, strWhere,null,false);
        }

        /// <summary>
        /// 操作类
        /// </summary>
        /// <typeparam name="T">需要操作的类</typeparam>
        /// <param name="t">需要操作的实体类</param>
        /// <param name="type">操作类型</param>
        /// <param name="index">当前页(用于分页查询)</param>
        /// <param name="size">每页条数(用于分页查询)</param>
        public bool ManageModel(ModelState type, int index, int size, string strWhere, string order, bool desc)
        {
            return ResultManage(type, index, size, strWhere, order,desc);
        }
        #endregion

        #region 分支判断
        private bool ResultManage(ModelState type, int? index, int? size, string strWhere,string order,bool desc, params object[] objs)
        {
            bool flag = false;
            switch (type)
            {
                case ModelState.Add:
                    //添加数据
                    flag = Add();
                    break;
                case ModelState.Delete:
                    //删除数据
                    flag = Delete(strWhere);
                    break;
                case ModelState.Select:
                    //查询数据
                    bool asce = false;
                    if (index != null)
                        ds_model=Select(index, size, strWhere, order, asce);
                    else
                        ds_model=Select(strWhere);
                    flag = false;
                    if (ds_model != null)
                        if (ds_model.Tables.Count > 0)
                            if (ds_model.Tables[0].Rows.Count > 0)
                                flag = true;
                    
                    break;
                case ModelState.Update:
                    //修改数据
                    flag = Edite(null);
                    break;
                default:
                    throw new Exception("当前类型不存在");
                    break;
            }
            return flag;
        }
        #endregion

        #region 数据库具体操作
        #region 新增
        private bool Add()
        {
            StringBuilder sql = new StringBuilder();
            sql.AppendLine("INSERT INTO [" + ti.TabelName + "](");
            bool index = false;
            bool index2 = false;
            StringBuilder value = new StringBuilder();
            foreach (PropertyInfo item in ti.TabelType.GetProperties())
            {
                //获取特性,再次验证
                bool again = false;
                object[] objs = item.GetCustomAttributes(typeof(BindFiledAttribute), false);

                foreach (BindFiledAttribute bfa in objs)
                {
                   
                    if (bfa.IsIdentity)
                        again = true;

                    if (bfa.IsIdentity)
                        continue;
                    if (index)
                        sql.AppendLine(",");
                    index = true;
                    sql.AppendLine(" [" + bfa.StrName+"]");
                }

                if (again)
                    continue;
                if (index2)
                    value.AppendLine(",");
                index2 = true;
                value.AppendLine("'" + item.GetValue(model, null) + "'");
            }
            sql.AppendLine(") VALUES (");
            sql.AppendLine("" + value.ToString());
            sql.AppendLine(")");
            return DBSqlServer.ExecuteSql(sql.ToString(), System.Data.CommandType.Text, null)>0;
        }
        #endregion

        #region 删除
        private bool Delete(string strWhere)
        {
            StringBuilder sql = new StringBuilder();

            try
            {
                sql.AppendLine("DELETE [" + ti.TabelName + "] ");
                if (string.IsNullOrEmpty(strWhere))
                {
                    //条件为空
                    foreach (PropertyInfo item in ti.TabelType.GetProperties())
                    {
                        //获取特性,再次验证
                        object[] objs = item.GetCustomAttributes(typeof(BindFiledAttribute), false);

                        bool fast = true;
                        foreach (BindFiledAttribute bfa in objs)
                        {
                            if (bfa.IsKey)
                            {
                                if (fast)
                                {
                                    sql.AppendLine(" WHERE ");
                                    fast = false;
                                }
                                sql.AppendLine(" [" + bfa.StrName + "]='" + item.GetValue(model, null) + "'");
                            }

                        }
                    }
                    return DBSqlServer.ExecuteSql(sql.ToString(), System.Data.CommandType.Text, null) > 0 ? true : false;
                }
                else
                {
                    //按条件查询
                    sql.AppendLine(" WHERE " + strWhere);
                    return DBSqlServer.ExecuteSql(sql.ToString(), System.Data.CommandType.Text, null) > 0 ? true : false;
                }

            }
            catch (Exception)
            {
                return false;
            }
        }

        #endregion

        #region 查询
        /// <summary>
        /// 普通查询
        /// </summary>
        /// <param name="strWhere">条件</param>
        /// <returns></returns>
        private DataSet Select(string strWhere)
        {
            StringBuilder sql = new StringBuilder();
            sql.AppendLine("SELECT ");
            bool fast = true;
            foreach (FileInfo fi in ti.Propretys)
            {
                if (!fast)
                    sql.AppendLine(",");
                fast = false;
                sql.AppendLine("["+fi.StrName+"]");
            }
            fast = true;
            sql.AppendLine(" FROM [" + ti.TabelName + "] ");
            if (!string.IsNullOrEmpty(strWhere))
            {
                sql.AppendLine("WHERE " + strWhere);
            }
            return DBSqlServer.ExecuteDataRead(sql.ToString(), CommandType.Text, null);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="index">当前页</param>
        /// <param name="size">每页数据量</param>
        /// <param name="strWhere">条件</param>
        /// <param name="order">排序字段</param>
        /// <param name="desc">是否倒序</param>
        /// <returns></returns>
        private DataSet Select(int? index, int? size, string strWhere, string order, bool desc)
        {
            StringBuilder sql = new StringBuilder();
            if (size <= 0 || index < 0)
                throw new Exception("超出参数表示范围.参数不可以小于0");

            sql.AppendLine("select top " + size + " ");

            bool fast = true;
            string key = "";
            foreach (FileInfo fi in ti.Propretys)
            {
                if (!fast)
                    sql.AppendLine(",");
                fast = false;

                sql.AppendLine(" ["+fi.StrName+"]");
                if (fi.IsKey)
                    key = fi.StrName;
            }
            sql.AppendLine(" FROM ["+ti.TabelName+"] WHERE ["+key+"] NOT IN(");

            sql.AppendLine("select top " + (size * (index - 1)) + " ["+key+"] FROM ["+ti.TabelName+"]");

            if (!string.IsNullOrEmpty(strWhere))
                sql.AppendLine(" WHERE "+strWhere);
            if(!string.IsNullOrEmpty(order))
                sql.AppendLine(" ORDER BY [" + order + "] " + (desc ? "DESC" : "ASC"));
            sql.AppendLine(")");
            return DBSqlServer.ExecuteDataRead(sql.ToString(), CommandType.Text, null);
        }

        #endregion

        #region 修改
        private bool Edite(string strWhere)
        {
            StringBuilder sql = new StringBuilder();
            //修改数据,1.是否有自定义条件
            if (string.IsNullOrEmpty(strWhere))
            {
                //根据主键修改
                sql.AppendLine("UPDATE [" + ti.TabelName + "] SET ");
                bool fast = true;
                foreach (PropertyInfo item in ti.TabelType.GetProperties())
                {
                    //获取特性,再次验证
                    object[] objs = item.GetCustomAttributes(typeof(BindFiledAttribute), false);


                    foreach (BindFiledAttribute bfa in objs)
                    {
                        if (bfa.IsKey || bfa.IsIdentity)
                        {
                            strWhere += "["+bfa.StrName + "]='" + item.GetValue(model, null) + "'";
                            continue;
                        }
                        if (!fast)
                            sql.AppendLine(",");
                        fast = false;
                        sql.AppendLine("[" + bfa.StrName + "]='" + item.GetValue(model, null) + "' ");
                    }
                }
                return DBSqlServer.ExecuteSql(sql.ToString() + " where " + strWhere, System.Data.CommandType.Text, null) > 0 ? true : false;

            }

            return false;
        }
        #endregion

        #endregion
    }

    public enum ModelState
    {
        Add, Select, Delete, Update
    }
View Code

这里有两个数据库公开操作方法,是为了便于程序编写自己的sql和调用存储过程而预留下来的.枚举ModelState是用于标识操作状态而预留的.

 这里可以下载源码和demo,大家也可以加我qq(1772282755).反馈意见,笔者是新手,还望多多指点 https://files.cnblogs.com/xufei/ORMAttriBute.rar

 

 

 

 

posted on 2013-11-04 09:22  源坊  阅读(1968)  评论(4编辑  收藏  举报

导航