C# 2.0 实现简单的ORM工具--MySql版本
2007-3-17 7:18:02
背景
06年8月份在公司用java实现了一套简单的orm工具,主要是针对jdk5.0提供的annotation特性,通过反射来实现对数据库操作的装箱、拆箱操作。 本来想放到blog上和大家共同share一下经验,后来测试jdk6.0的jdbc4.0特性时候发现jdbc4.0已经提供了类似类似orm的类库,只要db厂商实现某些接口,该厂商的bd-J-Driver就可以支持该特性了。目前主流的厂商还没有提供对jdbc4.0的支持,但是迟早要支持的,所以没有写这个部分。
后来改写成c#版本,和大家share一下。
可以把每个model类看作对应一个或者多个结构相同的表,因为有些应用我们要做分表操作。以下例子中以一个model类对应一个表为主。
核心思想是对类,以及对应的属性做上对应的标记,然后特定的工具通过对当前类的实例反射得到类上的标记,然后实现对数据库的相关操作。
c#里面提供了Attribue如果你对此不是很熟悉,请先看看相关资料有助于你对以下代码的理解。
我们先提供一个只对类起作用的Attribue,代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Reflection;namespace Moqee.Db.Annotations { /// <summary> /// 对类定义的属性 /// /// </summary> [AttributeUsage(AttributeTargets.Class,AllowMultiple=false,Inherited=false)] public class BeanAttribute:Attribute { //设置表名 private string tabname = ""; public string Tabname { get { return tabname; } set { tabname = value; } } //该类的所有字段是否自动映射 private bool afm = true; public bool Afm { get { return afm; } set { afm = value; } } public BeanAttribute() { } } }
BeanAttribute代码结束。 接下来实现一个对属性起作用的Attribute.
using System; using System.Collections.Generic; using System.Text; namespace Moqee.Db.Annotations { /// <summary> /// 定义一个对类public属性描述的注解类 /// </summary> [AttributeUsage(AttributeTargets.Property,AllowMultiple=true,Inherited=false)] public class PropertyAttribute:Attribute { /// <summary> /// 数据库表字段名称 /// </summary> private string fieldName = ""; public string FieldName { get { return fieldName; } set { fieldName = value; } } /// <summary> /// 对应的c#类型 /// </summary> private Type fieldCSType = typeof(string); public Type FieldCSType { get { return fieldCSType; } set { fieldCSType = value; } } /// <summary> /// 是否是主键 /// </summary> private bool isPrimary = false; public bool IsPrimary { get { return isPrimary; } set { isPrimary = value; } } /// <summary> /// 该方法是否映射 /// </summary> private bool isMapping = true; public bool IsMapping { get { return isMapping; } set { isMapping = value; } } private System.Data.DbType fieldDbType; public System.Data.DbType FieldDbType { get { return fieldDbType; } set { fieldDbType = value; } } } }
代码完毕。
下面有一个测试model类。
using System; using System.Collections.Generic; using System.Text; using Moqee.Db.Annotations; using Moqee.Common; namespace Moqee.Book.Business { [Bean(Tabname="T_CATALOG",Afm=true)] public class Catalog { private long guid; private int status = BookConstants.OPEN_STATUS; private int priority = 0; [Property(FieldName="priority",FieldCSType=typeof(Int32))] public int Priority { get { return priority; } set { priority = value; } } [Property(FieldName="status",FieldCSType=typeof(Int32))] public int Status { get { return status; } set { status = value; } } [Property(FieldCSType=typeof(Int64),FieldName="guid",IsPrimary=true)] public long Id { get { return guid; } set { guid = value; } } private string name; [Property(FieldName="name",FieldCSType=typeof(string))] public string Name { get { return name; } set { name = value; } } } }
下面看如何解析这个类以得到里面的数据类型
private void ParserClassTag(Type type) { object[] atts = type.GetCustomAttributes(typeof(BeanAttribute), false); if (atts == null||atts.Length==0) return null; BeanAttribute pa = (BeanAttribute)atts[0]; PropertyInfo[] props = type.GetProperties(); if (props == null) return null; //此处可以得到props里面的所有属性 foreach (PropertyInfo pi in props) { atts = pi.GetCustomAttributes(typeof(PropertyAttribute), false); if (atts == null || atts.Length == 0) continue; PropertyAttribute patt = (PropertyAttribute)atts[0]; ///此处可以得到里面的所有属性, }
} 经过上面的方法,就可以得到所定义的说有属性值,可以得到表名,字段信息,insert,update等语句都可以预先得到。
如果你的应用是mysql,并且主键是自增类型,完全可以定义bean里面的主键小于0为insert否则为update。
可以定义一个 DAO接口实现一些方法。
void save(object obj) throws Exception; void delete(object obj) throws Exception; void find(object obj) throws Exception; List<E> query(object obj) throws Exception; .......等等方法。
可以定义一个cache工具来实现对对类属性的缓存,不用每次都动态解析属性。
java版本的思路和上面非常类似,有兴趣你可以自己实现一下。
|