在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
今天在这里写一套简单的框架,主要用于一些小型的项目,用于数据的增删改查,通用分页查询等操作.所以功能并不强大,而且笔者也是新手,这里面也难免会有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 } _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 } _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 } 怎么样,是不是很轻松呢,好,我们继续向下说 特性已经出现了,那么我们必定需要有一个地方来存储我们所标识的实体对应的值,所以笔者在这定义了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; } } 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("没有找到您想要删除的数据集"); } } _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(); } } 这里主要是让他起到自动缓存和读取的作用,不至于我们忘记缓存等操作而增加操作 好,现在我们的第一步工作算是完成了,我们进入第二步工作,数据库的连接和数据库操作等 这里我们可以重新创建类库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 如此,我们便可以写创建表和列的字符串了 /// <summary> /// 创建表 /// </summary> /// <param name="ti">数据源</param> /// <returns></returns> private 全部评论
专题导读
热门推荐
热门话题
阅读排行榜
|
请发表评论