WSORM:为WSBLog写的简单ORM(一)
我曾经说过:我心目中的下一个版本的WSBLog,是要用ORM去做,并且,是专门写一个ORM,不需要多复杂,够用就好。
至于怎么才算够用?我的想法是:尽可能得减少WSBLog在数据访问方面的代码;在不修改WSBLog的代码的情况下,能将WSBLog无缝地移植到几个主流的数据库:Sql Server、Accesss、Oracle、MySql。
我将这个ORM暂且命名为:WSORM,可以理解为:WSBLog's Simple ORM——为WSBLog实现的简单ORM。呵呵。
我做这个东西的时候,没有使用过Hibernate、iBatis等任何一种产品,更谈不上参考他们的源代码了。我只是从我所知道的ORM的一些皮毛中想象出我要做的WSORM的样子。所以呢,使用ORM的行家估计看了要排砖了。嘿嘿。
目前的WSORM对Sql Server的支持已经基本实现了,当然,BUG是免不了的。代码也不算优雅,还是慢慢搞吧。
至于对Oracle的支持,实现了一部分。而且我相信,对于Access的实现起来应该会简单得多,在我看来,从支持Sql Server改到支持Access,要改动的代码很少。我打算下一步把对在Oracle上的实现先放一放,先做Access的再说。
感兴趣的朋友,可以到我的BLOG下载一下预览版本:
http://www.wubuku.com
这份源代码可以编译成类库dll,也可以直接编译成一个可执行的测试程序。更改一下项目属性就可以了。
要运行测试程序,需要Sql Server上安装了Northwind样本数据库——这个我相信搞过Sql Server的都知道是什么东西吧?还有就是可能需要修改一下源代码中测试程序使用的数据库连接字符串。
这个WSORM怎么用呢?
就拿测试程序中的代码来说一下吧:
首先定义和Northwind中的订单表、订单明细表、产品信息表对应的几个类,然后定义一下这些类和数据表之间的影射关系。
订单类对应订单表Orders的Field成员和Property成员定义如下:
复制内容到剪贴板
代码:
private int id;
//ID定义为Property
public int ID
{
get{ return this.id; }
set{ this.id = value; }
}
//其他的字段定义为Field
public string CustomerID ;
public int EmployeeID ;
public DateTime OrderDate;
public DateTime RequiredDate;
public DateTime ShippedDate;
public int ShipVia;
public decimal Freight;
public string ShipName;
public string ShipAddress;
public string ShipCity;
public string ShipRegion;
public string ShipPostalCode;
public string ShipCountry;
//注意这个地方,定义为订单明细类对象的数组
public OrderDetail[] Details;订单类Order和数据库中的订单表Orders之间的影射关系定义如下:
复制内容到剪贴板
代码:
public static ObjectMap GetObjectMap()
{
ObjectMap omap = new ObjectMap(typeof(Order),"Orders");
omap.MemberMaps.Add("ID","OrderID", DbFieldTypes.Int, MemberMapTypes.Identity);//[OrderID] [int] IDENTITY (1, 1) NOT NULL ,
omap.MemberMaps.Add("CustomerID", "CustomerID", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("EmployeeID", "EmployeeID", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("OrderDate", "OrderDate", DbFieldTypes.DateTime, MemberMapTypes.NormalField);
omap.MemberMaps.Add("RequiredDate", "RequiredDate", DbFieldTypes.DateTime, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ShippedDate", "ShippedDate", DbFieldTypes.DateTime, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ShipVia", "ShipVia", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("Freight", "Freight", DbFieldTypes.Money, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ShipName", "ShipName", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ShipAddress", "ShipAddress", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ShipCity", "ShipCity", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ShipRegion", "ShipRegion", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ShipPostalCode", "ShipPostalCode", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ShipCountry", "ShipCountry", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("Details","OrderID", DbFieldTypes.Int, typeof(OrderDetail), "OrderID", MemberMapTypes.One2Many);
return omap;
}订单明细类OrderDetail的成员定义如下:
复制内容到剪贴板
代码:
public int OrderID;
public int ProductID;
public Decimal UnitPrice;
public int Quantity;
public float Discount;
//注意这个地方,产品信息不是基本类型
public Product Product;订单明细类OrderDetail和数据表Order Details的影射关系定义如下:
复制内容到剪贴板
代码:
public static ObjectMap GetObjectMap()
{
ObjectMap omap = new ObjectMap( typeof(OrderDetail),"Order Details");
omap.MemberMaps.Add("OrderID", "OrderID", DbFieldTypes.Int, MemberMapTypes.PrimaryKey);
//联合主键
// [ProductID] [int] NOT NULL ,
omap.MemberMaps.Add("ProductID", "ProductID", DbFieldTypes.Int, MemberMapTypes.PrimaryKey); //联合主键
// [UnitPrice] [money] NOT NULL ,
omap.MemberMaps.Add("UnitPrice", "UnitPrice", DbFieldTypes.Money, MemberMapTypes.NormalField);
omap.MemberMaps.Add("Quantity", "Quantity", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("Discount", "Discount", DbFieldTypes.Real, MemberMapTypes.NormalField);
//Many 2 One
omap.MemberMaps.Add("Product", "ProductID", DbFieldTypes.Int, typeof(Product), "ProductID", MemberMapTypes.Many2One);
return omap;
}再看一下产品信息类以及它和数据表之间的影射关系:
复制内容到剪贴板
代码:
public class Product
{
public static ObjectMap GetObjectMap()
{
ObjectMap omap = new ObjectMap(typeof(Product),"Products");
omap.MemberMaps.Add("ID", "ProductID", DbFieldTypes.Int, MemberMapTypes.Identity);
omap.MemberMaps.Add("ProductName", "ProductName", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("SupplierID", "SupplierID", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("CategoryID", "CategoryID", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("QuantityPerUnit", "QuantityPerUnit", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("UnitPrice", "UnitPrice", DbFieldTypes.Money, MemberMapTypes.NormalField);
omap.MemberMaps.Add("UnitsInStock", "UnitsInStock", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("UnitsOnOrder", "UnitsOnOrder", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ReorderLevel", "ReorderLevel", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("Discontinued", "Discontinued", DbFieldTypes.Boolean, MemberMapTypes.NormalField);
#if USE_VERSION_LOCK
//如果需要使用版本控制,需要在Products表中添加一个Version字段,Product添加一个Version成员,然后添加以下字段影射
omap.MemberMaps.Add("Version", "Version", DbFieldTypes.Int, MemberMapTypes.Version);
#endif
return omap;
}
public int ID;
public string ProductName;
public int SupplierID;
public int CategoryID;
public string QuantityPerUnit;
public decimal UnitPrice;
public int UnitsInStock;
public int UnitsOnOrder;
public int ReorderLevel;
public bool Discontinued;
public int Version;
public Product()
{
//构造函数
}
}定义好这些“实体类”和影射信息后,怎么用呢?请看下一篇文章……