SmartPersistenceLayer 3 快速入门
前言
SmartPersistenceLayer(SPL)自在博客园发布开始,就一直受到广大朋友的认可,那一套SPL的系列文档对SPL的使用与功能以及原理都作了充分的介绍,而这些系列文章有利于大家理解SPL的思想,将作为一个优秀的.NET系统框架持久层。
而那些文章由于比较分散,而且论述了一些架构思想,对一些初学者感觉有些困难,也应广大朋友的要求,写一份简单的、实用的SPL应用手册,所以我接下来从实际场景模拟开发。SPL强调是框架带来的灵活性与扩展性。
一、 引用
SPL的发布形式是一个名为PersistenceLayer.Dll的DLL文件,可以在我的BLOG上下载目前最新版:SmartPersistenceLayer3.2,因此只需要在项目中“添加引用”即可:
若要使用ODP.NET连接Oracle数据库,则用以上方式添加Oracle.DataAccess.dll
若要使用SPL连接MySql数据库,则用以上方式添加MySql.Data.dll
二、 配置文件与实体类
SPL的配置文件与实体类可以使用我提供的SmartRobot进行生成(SPL_Robot已经公开源码,请看这里),这可以大大加快开发效率,但工具毕竟是工具,不属于SPL持久层的必选部分。
连接数据库:
目前SmartRobot支持Ms Sql Server、Ms Access、Oracle数据库,如果是其他数据库只能只好手写实体类了或者等我升级喽;)
确定好要生成的实体类存放的地址,到时生成时会生成到相应的目录里。
配置每个表对应的实体类属性,默认实体类名称为“表名”加“Entity”字符,属性名默认与列名相同,上图中的“2”“3”操作对每个表都要重复一次的。
这时就会生成勾上的实体类到指定的目录下了。只要把指定的实体类引用到项目中即可,实体类默认使用的是BusinessEntity命名空间。因此在开发时,只要用到实体类的地方使用:using BusinessEntity就可以了。
保存两个配置文件,放到你的项目中:ClassMap.xml与DatabaseMap.xml
ClassMap.xml为数据库表与实体类的映射关系
DatabaseMap.xml为数据库连接配置:
Ms Sql Server例如下:
<parameter name="Provider" value="SQLOLEDB.1" />
<parameter name="Password" value="tintown" />
<parameter name="Initial Catalog" value="Northwind" />
<parameter name="User ID" value="sa" />
<parameter name="Data Source" value="(local)" />
<classMapFile path="ClassMap.xml" />
</database>
Ms Access例如下:
<parameter name="Provider" value="Microsoft.Jet.OLEDB.4.0" />
<parameter name="Data Source" value="dmbcn.mdb" />
<classMapFile path="ClassMap.xml" />
</database>
Oracle例如下:
<parameter name="Provider" value="MSDAORA.1" />
<parameter name="Password" value="tintown" />
<parameter name="User ID" value="EDI" />
<parameter name="Data Source" value="EDI.LIHINSOFT.COM" />
<classMapFile path="ClassMap.xml" />
</database>
ODP.NET方式连接Oracle例如下:
<parameter name="Password" value="tintown" />
<parameter name="User ID" value="acci" />
<parameter name="Data Source" value="oradb" />
<parameter name="Persist Security Info" value="False" />
<classMapFile path="ClassMap.config" />
</database>
MySql数据库例如下:
<parameter name="User Id" value="root"/>
<parameter name="Data Source" value="localhost"/>
<parameter name="Database" value="mysql"/>
<parameter name="password" value="tintown"/>
<classMapFile path="ClassMap.xml" />
</database>
ClassMap.xml的地址是相对于DatabaseMap.xml地址的,象例子中都是放在同一目录下,所以直接使用文件名即可.
如果是连接多数据库,则可以配置多个<database>节 如:
<database name="Northwind" type="MsSqlServer">
<parameter name="Provider" value="SQLOLEDB.1" />
<parameter name="Password" value="tintown" />
<parameter name="Initial Catalog" value="Northwind" />
<parameter name="User ID" value="sa" />
<parameter name="Data Source" value="(local)" />
<classMapFile path="ClassMap.xml" />
</database>
<database name="MySql" type="MySql">
<parameter name="User Id" value="root"/>
<parameter name="Data Source" value="localhost"/>
<parameter name="Database" value="mysql"/>
<parameter name="password" value="tintown"/>
<classMapFile path="ClassMap2.xml" />
</database>
</map>
所示为同时连接Ms Sql Server数据库与MySql数据库
三、 初始化数据连接
在页面的Page_Onload中使用如下进行初始化(假设DatabaseMap.xml放在Config目录下):
PersistenceLayer.Setting.Instance().DatabaseMapFile=Server.MapPath(DatabaseXml);
以上的初始化只需要执行一次即会放在应用项目中,但Web会经常性的丢失Application,导致初始信息丢失,因此在每次执行数据库操作前都最好能进行初始化。
建议大家可以放在BasePage中,采用Appliction进行控制:
{
string DatabaseXml="Config/DatabaseMap.xml";
PersistenceLayer.Setting.Instance().DatabaseMapFile=Server.MapPath(DatabaseXml);
Application["DatabaseSetting"]="Y";
}
因为生成的实体类都是在BusinessEntity命名空间下的,所以在要使用数据库访问的页面上加上:
Using BusinessEntity;
就可以直接使用SPL的类与实体类了。
好了,非常简单,现在就可以开始体验SPL了。
四、 开发
假设我们目前有订单对象SaleOrder(字段名与属性名相同):
字段名 |
类型 |
描述 |
Id |
Varchar(50) |
GUID主键 |
No |
Varchar(50) |
订单编号 |
CustomId |
Varchar(50) |
客户ID |
CreateDate |
DateTime |
下单日期 |
|
|
|
订单明细对象SaleOrderDetail(字段名与属性名相同):
Id |
Varchar(50) |
GUID主键 |
OrderId |
Varchar(50) |
订单的ID(外键) |
ProductId |
Varchar(50) |
产品ID(外键) |
Quantity |
Int |
需求数量 |
Price |
Decimal |
单价 |
Amount |
Decimal |
小计 |
以下为模拟情况:
在界面上选择了客户,并在Grid里选择了产品并输入了单价与数量,生成新订单
SaleOrderEntity Soe=new SaleOrderEntity();
Soe.Id=Guid.NewGuid().ToString(); //生成新GUID
Soe.No=this.txtNo.Text; //取文本框里值
Soe.CustomId=this.ddlCustom.SelectedValue; //取界面上客户下拉框里值
Soe.CreateDate=System.DateTime.Now; //取当前日期
t.AddSaveObject(Soe); //把订单主档加到事务中
for(int i=0;i<this.Grid.Rows.Count;i++) //编历整个Gruid生成一条条明细保存
{
SaleOrderDetailEntity Sode=new SaleOrderDetailEntity();
Sode.Id=Guid.NewGuid().ToString();//生成新的GUID
Sode.OrderId=Soe.Id; //取订单主档的GUID
Sode.ProductId=…//从Grid上取商品ID值
Sode.Quantity= //从Grid上取商品数量值
Sode.Price=… //从Grid上取商品单价值
Sode.Amount=Sode.Quantity*Sode.Price; //汇总小计
t.AddSaveObject(Sode); //把订单明细对象加到事务中
}
t.Process(); //事务提交即可
在查询界面要根据订单编号、订单时间段、客户进行综合查询
Condition c=rc.GetNewCondition();//创建一个条件(由于是综合查询,条件之间是AND关系)
If(this.txtNo.Text!=””) //如果在编号文本框中输入了查询条件
c.AddEqualTo(SaleOrderEntity.__NO,this.txtNo.Text);//添加”=”条件(SaleOrderEntity.__NO是实体类中的常量,其值就是”No”,为了减少去查对象属性的麻烦和输错的可能性,采用常量是最好的方式)
if(this.ddlCustom.SelectedValue!=””) //如果选择了某一客户
c.AddEqualTo(SaleOrderEntity.__CUSTOMID, this.ddlCustom.SelectedValue);
if(this.txtDateFrom.Text!=””) //如果开始日期不为空,则添加”>=”比较
c. AddGreaterThanOrEqualTo(SaleOrderEntity.__CREATEDATE,DateTime.Parse(this.txtDateFrom.Text);
if(this.txtDateEnd.Text!=””)//如果结束日期不为空,则添加”<”比较
c. AddLessThan(SaleOrderEntity.__CREATEDATE,DateTime.Parse(this.txtDateEnd.Text).AddDays(1);
rc.OrderBy(SaleOrderEntity.__CREATEDATE,false);//按创建时间的逆顺排
DataTable dt=rc.AdDataTable(); //返回DataTable以便绑定Grid
选中一条档后要显示主档信息与明细清单
Soe.Id=Request[“Id”].ToString(); //取得页面传过来的订单ID值
Soe.Retrieve(); //通过主键值获取对象
If(Soe.IsPersistent) //如果数据库里存在的话
{
//给界面上的控件赋值显示
this.txtNo.Text=Soe.No;
this.txtCreateDate.Text=Soe.CreateDate.ToString();
….
//绑定订单的所有明细信息
RetrieveCriteria rc=new RetrieveCriteria(typeof(SaleOrderDetailEntity));
Condition c=rc.GetNewCondition();
c.AddEqualTo(SaleOrderDetailEntity.__ORDERID,Soe.Id);//指定的订单ID
DataTable dt=rc.AsDataTable(); //返回明细DataTable
this.Grid.DataSource=dt;
this.Grid.DataBind();//绑定
}
进行订单主档与明细的修改,点击保存时
SaleOrderEntity Soe.new SaleOrderEntity();
Soe.Id=Request[“Id”].ToString(); //取得订单ID
Soe.Retrieve();//通过主键获取对象
If(Soe.IsPersistent) //如果对象存在的话进行修改操作
{
Soe.No=this.txtNo.Text;
Soe.CreateDate=DateTime.Parse(this.txtCreateDate.Text);
….
t.AddSaveObject(Soe); //自动判断IsPersistent就进行Update而不是Insert
//选删除所有的明细记录,然后再重新把明细添进去,这样比较方便,避免了要判断是否进行修改,是否要进行删除与新增的麻烦
DeleteCriteria dc=new DeleteCriteria(Typeof(SaleOrderDetailEntity));//创建一个针对SaleOrderDetail的删除标准
dc.GetNewCondition().AddEqualTo(SaleOrderDetailEntity.__ORDERID,Soe.Id);//删除所有本订单ID的明细
t.AddDeleteCriteria(dc);//把这个删除标准加到事务中
for(int i=0;i<this.Grid.Rows.Count;i++) 循环Grid重新添加到明细表中
{
SaleOrderDetailEntity Sode=new SaleOrderDetailEntity();
Sode.Id=Guid.NewGuid().ToString();//生成新的GUID
Sode.OrderId=Soe.Id; //取订单主档的GUID
Sode.ProductId=…//从Grid上取商品ID值
Sode.Quantity= //从Grid上取商品数量值
Sode.Price=… //从Grid上取商品单价值
Sode.Amount=Sode.Quantity*Sode.Price; //汇总小计
t.AddSaveObject(Sode); //把订单明细对象加到事务中
}
}
删除订单与订单明细
SaleOrderEntity Soe.new SaleOrderEntity();
Soe.Id=Request[“Id”].ToString(); //取得订单ID
Soe.Retrieve();//通过主键获取对象
If(Soe.IsPersistent) //如果对象存在的话进行修改操作
{
t.AddDeleteObject(Soe); //把要删除的对象加到事务中
//选删除所有的明细记录
DeleteCriteria dc=new DeleteCriteria(Typeof(SaleOrderDetailEntity));//创建一个针对SaleOrderDetail的删除标准
dc.GetNewCondition().AddEqualTo(SaleOrderDetailEntity.__ORDERID,Soe.Id);//删除所有本订单ID的明细
t.AddDeleteCriteria(dc);//把这个删除标准加到事务中
t.Process();//提交删除
}
以上是我模拟的最常见的一些情况,让大家对SPL的使用有个初步的了解,如果大家有其他模拟情况疑问,可以提出来。
至于SPL的更多的详细资料请访问我的BLOG专题:http://tintown.cnblogs.com/category/12787.html
本文下载:点此下载
听棠
2005-12-5