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++;
      
        }
    }


 

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

posted @ 2011-08-01 16:55  架构师修行之路  阅读(2365)  评论(9编辑  收藏  举报