zoukankan      html  css  js  c++  java
  • DAN疼之后上些基础知识自己的ORM

    在我”很小“的时候曾经有一个同事,工作经验比较丰富的那种,当时asp.net还处在2.0 时代,做项目的时候当时还流行三层,我当时是个菜鸟(现在也是),看那个同事做三层的时候,早model层的属性和类上边加上一个特性,就可以实现这个类的增删改查,对于当时的我来说,已经很先进了。。。。

    过了2年,虽然我依然很菜,但是在今天这个令人蛋疼的日子里,突然想起了这个功能,反正疼着也是疼着,不如来实现一下,顺便看看自己能不能做出来,经过了一天多的折腾,终于实现了其中简单的一点,不敢拿出来让大湿们look,只希望与刚工作的童鞋们一起分享一下,以共勉!!

    环境:asp.net 4.0   +  vs2010 +windows 2003 +SQL2005

    一:特性部分:

      

        [AttributeUsage(AttributeTargets.Class ,AllowMultiple =false , Inherited =true )]
    public class TableAttribute:Attribute ,IError
    {
    public TableAttribute(string name)
    {
    if (!string.IsNullOrEmpty(name))
    {
    this.Name = name;
    }
    else
    {
    this.ErrorMessage = "TableAttribute必须对name进行初始化";
    }
    }


    //表名
    public string Name { get; set; }
    //记录程序中的错误信息
    public string ErrorMessage { get; set; }

    }

    因为我的这个orm,其实也不能算是orm,把表和列的特性分开了,所以会有两个类

        [AttributeUsage(AttributeTargets.Property |AttributeTargets .Field , AllowMultiple = false, Inherited = true)]
    public class ColumnAttribute:Attribute ,IError
    {
    public ColumnAttribute(string name, bool isAutomatic = false)
    {
    if (!string.IsNullOrEmpty(name))
    {
    this.Name = name;
    }
    else
    {
    this.ErrorMessage = "ColumnAttribute必须对name进行初始化";
    }
    this.IsAutomatic = isAutomatic;
    }


    //表名
    public string Name { get; set; }
    //记录程序中的错误信息
    public string ErrorMessage { get; set; }
    //是否为自动增长,默认为false
    public bool IsAutomatic { get; set; }
    }

    对于其中的一些写法,无非是4.0里边的默认参数,还有以下的 扩展方法等等,木有什么高深的代码

    二:model部分

      

       [Table("student")]
    public class Student:IModel
    {
    [Column(
    "id", IsAutomatic = true)]
    public int ID { get; set; }
    [Column(
    "name")]
    public string Name { get; set; }
    [Column(
    "age")]
    public int Age { get; set; }
    [Column(
    "date")]
    public DateTime date { get; set; }
    }

    三:数据库和类映射部分

      我相信这部分就是像我这样的菜鸟最关心的部分了,为了作为数据的承载和缓存我新建了两个类,、

        public  class TableDTO
    {
    public string TablaName { get; set; }
    public List<ColumnDTO> TableColumn { get; set; }
    public IModel Class { get; set; }
    }
    public class ColumnDTO
    {
    public string ColumnName { get; set; }
    public PropertyInfo Property { get; set; }
    }

    接下来就是正式的转化部分了,具体也不知道怎么讲,一看代码大家就明白了,

     public static class ConvertToTable 
    {

    /// <summary>
    /// 将model类型转化为表-列的形式
    /// </summary>
    /// <returns></returns>
    public static TableDTO GetTable<T>(this T t) where T :class ,IModel,new ()
    {
    var model
    = AttributeDic.Dics.FirstOrDefault(s=>s .Key ==typeof (T)) ;
    if (model.Key !=null )
    {
    return model.Value;
    }
    var attribute
    = typeof(T).GetCustomAttributes(typeof(TableAttribute),true );
    TableDTO table
    = new TableDTO();
    table.TablaName
    = (attribute[0] as TableAttribute).Name;
    table.Class
    =new T();
    PropertyInfo[] infos
    = typeof(T).GetProperties();

    List
    <ColumnDTO> columns = new List<ColumnDTO>();
    foreach (PropertyInfo info in infos)
    {
    ColumnDTO column
    = new ColumnDTO();

    if (info.GetCustomAttributes(typeof(ColumnAttribute), true).Length > 0)
    {
    column.ColumnName
    = (info.GetCustomAttributes(typeof(ColumnAttribute), true)[0] as ColumnAttribute).Name;
    column.Property
    = info;
    }


    columns.Add(column);
    }
    table.TableColumn
    = columns;
    if (!AttributeDic.Dics.ContainsKey (typeof(T)))
    {
    AttributeDic.Dics.Add(
    typeof(T), table);
    }

    return table;
    }


    }

    这里关于IModel 这个借口没有什么好说的,纯粹就是一个约束而已,里边没有任何内容,关于PropertyInfo不熟悉的同学,自己可以查以下msdn,上边写的比我说的要清楚的多,至于AttributeDic.Dics 这个变量,纯粹是一个容器功能而已

     public  class AttributeDic
        {
            /// <summary>
            /// 作为缓存使用:<表明.列名,类名.属性名>
            /// </summary>
            public static Dictionary<Type, TableDTO> Dics = new Dictionary<Type, TableDTO>();
        }
    

    四:使用部分:

    因为作为演示,所以我只做了一个插入数据的功能,扩展的同学自己可以发挥以下想想

     public static  class Operate
        {
           public static int Insert<T>(this T t, string where="") where T: class ,IModel,new ()
           {
    
               TableDTO dto = ConvertToTable.GetTable(t);
               List<ColumnDTO> columns = dto.TableColumn.Where(s => s.Property.GetValue(t, null)!=null ).ToList();
    
               StringBuilder strSql = new StringBuilder();
               StringBuilder sbcolumn = new StringBuilder();
               StringBuilder sbvalue = new StringBuilder();
    
               int count=columns .Count;
               SqlParameter[] para=new SqlParameter [count];
               int index=0;
               foreach (ColumnDTO columndto in columns)
               {
                    
                   if ((columndto .Property .GetCustomAttributes(typeof(ColumnAttribute), true)[0] as ColumnAttribute).IsAutomatic == true)
                   {
                       para = new SqlParameter[count-1];
                       continue;
                       
                   }
                   sbcolumn.Append(columndto.ColumnName).Append(",");
                   sbvalue.Append("@").Append(columndto.ColumnName).Append(",") ;
    
                   para[index] = new SqlParameter("@"+columndto .ColumnName , columndto.Property.GetValue(t, null));
                   index++;
               }
               string strcolumn=sbcolumn.ToString();
               string strvalue = sbvalue.ToString();
               strSql.Append("insert into ").Append(dto.TablaName).Append(" (").Append(strcolumn.Substring(0, strcolumn.Length - 1)).Append(") values (").Append(strvalue .Substring (0,strvalue .Length -1)).Append(")");
    
               SqlHelper.ExecuteNonQuery(SqlHelper .ConnectionString ,CommandType.Text ,strSql .ToString (),para );
               return 1;
           }
    
        }
    

    这部分无非就是拼接sql语句,构造参数而已,木有好讲的,仔细看一下就明白了,实现的比较粗糙,至于sqlhelper,我向大家都用过了,更不用多说了

    现在来看客户端的调用:为了避免重复,我加了一个静态字段来标示不同

     public partial class WebForm1 : System.Web.UI.Page
        {
            private static int index = 0;
            protected void Page_Load(object sender, EventArgs e)
            {
              
            }

            protected void Button1_Click(object sender, EventArgs e)
            {
                Student stu = new Student() { Name ="姓名"+index , Age =index ,date =DateTime .Now };
                stu.Insert();
                index++;
          
            }
        }


     

    我从早就发现我自己真的不会写博客,大家看代码吧,比较清楚,嗨,小学语文没学好

  • 相关阅读:
    php中除法取整的方法(round,ceil,floor)
    ajax 实现修改功能
    ueditor PHP版本使用方法
    $.ajax json 在本地正常 上传服务器不正常
    Web常见几种攻击与预防方式
    PHP使用Session遇到的一个Permission denied Notice解决办法
    VUE引入模块之import xxx from 'xxx' 和 import {xxx} from 'xxx'的区别
    JS事件委托或者事件代理原理以及实现
    JS 一次性事件问题
    原生JS 和 JQ 获取滚动条的高度,以及距离顶部的高度
  • 原文地址:https://www.cnblogs.com/zhanlang/p/2124047.html
Copyright © 2011-2022 走看看