Snake.Net 框架中的ORM(二) (Version 0.2 Beta)

 

4.业务实体的设计

ORM实现了业务实体对象与数据表,实体属性或域与数据字段之间的对应关系。在这种条件下:一方面,可以通过Snake.Net框架的处理机制,屏蔽各种数据库差异,自动生成数据访问的SQL语句,实现对象的CRUD(Create, Retrieve, Update, Delete方法)操作和复杂查询功能;另一方面ORM可以使数据库操变为对象操作,使OO的编程理念与数据访问完美的结合起来。

通常情况下,ORM中的每个业务实体都与一个数据表相对应,而实体内的属性或域则与数据表内的字段相对应。Snake.Net提供了DataMappingObject, DataRowObjectDataBindObject等多种基类,可以使用不同类型的数据映射技术,从而满足各种开发环境的需要。

       1)实体类的定义

              ADataMappingObject对象

DataMappingObject 实现了 DataTable 的构架定义与业务实体的属性或域进行映射。我们以著名的示例数据库 Northwind 为例,根据其中的 Shippers 表定义一个 Shipper 对象。请看下面的代码。

None.gif using  System;
None.gif
using  Eastasp.Enterprise;
None.gif
using  Eastasp.Enterprise.ORM;
None.gif
None.gif
namespace  Eastasp.Samples
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public class Shipper:DataMappingObject
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
protected string pcompanyName;
InBlock.gif        
protected string pphone;
InBlock.gif        
protected int pshipperID;
InBlock.gif        
InBlock.gif        
public Shipper():base()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        
public string CompanyName
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
getdot.gif{return (string)GetValue(pcompanyName);}
ExpandedSubBlockStart.gifContractedSubBlock.gif            
setdot.gif{pcompanyName = (string)SetValue(pcompanyName, value);}
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public string Phone
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
getdot.gif{return (string)GetValue(pphone);}
ExpandedSubBlockStart.gifContractedSubBlock.gif            
setdot.gif{pphone = (string)SetValue(pphone, value);}
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int ShipperID
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
getdot.gif{return (int)GetValue(pshipperID);}
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

B)DataRowObject对象
DataRowObject对象内置了一个DataRow变量,其公共的属性是通过获取或设置DataRow中的字段值实现的。再以Shippers为列定义一个Shipper对象。请看下面的代码。

None.gif using  System;
None.gif
using  System.Data;
None.gif
using  Eastasp.Enterprise;
None.gif
using  Eastasp.Enterprise.ORM
None.gif
None.gif
namespace  Eastasp.Samples
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public class Shipper:DataRowObject
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public Shipper():base()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public string CompanyName
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
getdot.gif{return (string)GetValue("CompanyName");}
ExpandedSubBlockStart.gifContractedSubBlock.gif            
setdot.gif{SetValue("CompanyName", value);}
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public string Phone
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
getdot.gif{return (string)GetValue("Phone");}
ExpandedSubBlockStart.gifContractedSubBlock.gif            
setdot.gif{SetValue("Phone", value);}
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int ShipperID
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
getdot.gif{return (int)GetValue("ShipperID");}
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif


 

CDataBindObject对象

DataBindObject ,是通过 Attribute 特性,声明实现业务实体的属性或域与数据表的映射关系。再以 Shippers 为列定义一个 Shipper 对象。请看下面的代码。


None.gif using  System;
None.gif
using  Eastasp.Enterprise;
None.gif
using  Eastasp.Enterprise.ORM;
None.gif
None.gif
namespace  Eastasp.Samples
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    [TableMapping(
"Shippers")]
InBlock.gif    
public class Shipper:DataBindObject
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        [ColumnMapping(
"ShipperID", IsPrimaryKey=true, AutoIncrement=true)]
InBlock.gif        
protected int pshipperID;
InBlock.gif        
protected string pcompanyName;
InBlock.gif        
protected string pphone;
InBlock.gif
InBlock.gif        
public Shipper():base()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        [ColumnMapping(
"CompanyName")]
InBlock.gif        
public string CompanyName
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
getdot.gif{return pcompanyName;}
ExpandedSubBlockStart.gifContractedSubBlock.gif            
setdot.gif{pcompanyName = value;}
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        [ColumnMapping(
"Phone")]
InBlock.gif        
public string Phone
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
getdot.gif{return pphone;}
ExpandedSubBlockStart.gifContractedSubBlock.gif            
setdot.gif{pphone = value;}
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public int ShipperIDdot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
getdot.gif{return pshipperID;}
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif



(2)数据映射
 对于不同的对象,Sanke.Net使用不同的方法进行数据映射。DataMappingObject和DataRowObject对象通过DataSet的定义文件与业务实体进行映射。首先我们在DataSet定义内引入xmlns:msprop="urn:schemas-microsoft-com:xml-msprop"命名空间(如图 4-2-1),然后使用msprop:Mapping属性将数据表映射对应的业务实体类型名称,将数据字段映射到对应的属性或域的名称。(如图 4-2-2)

None.gif <? xml version="1.0" encoding="utf-8"  ?>
None.gif
< xs:schema  id ="orm"  targetNamespace ="http://tempuri.org/orm.xsd"  elementFormDefault ="qualified"  attributeFormDefault ="qualified"  xmlns ="http://tempuri.org/orm.xsd"  
None.gifxmlns:mstns
="http://tempuri.org/orm.xsd"     xmlns:xs ="http://www.w3.org/2001/XMLSchema"  
None.gifxmlns:msdata
="urn:schemas-microsoft-com:xml-msdata"  
None.gifxmlns:msprop="urn:schemas-microsoft-com:xml-msprop"
>
None.gif    
< xs:element  name ="orm"  msdata:IsDataSet ="true" >
None.gif    
</ xs:element >
None.gif
</ xs:schema >
None.gif

4-2-1 引入urn:schemas-microsoft-com:xml-msprop命名空间

None.gif <? xml version="1.0" encoding="utf-8"  ?>
None.gif
< xs:element  name ="Shippers"  msprop:Mapping="Eastasp.Samples.Shipper"  msprop:Alias ="Shipper" >
None.gif    
< xs:complexType >
None.gif        
< xs:sequence >
None.gif            
< xs:element  name ="ShipperID"  msdata:AutoIncrement ="true"  type ="xs:int"  msprop:Mapping="pshipperID"   />
None.gif            
< xs:element  name ="CompanyName"  type ="xs:string"  minOccurs ="0"   />
None.gif            
< xs:element  name ="Phone"  type ="xs:string"  minOccurs ="0"   />
None.gif        
</ xs:sequence >
None.gif    
</ xs:complexType >
None.gif
</ xs:element >
None.gif
4-2-2 设置数据表和字段对应的映射关系

DataBindObject对象使用TableMappingAttributeColumnMappingAttribute特性分别将业务实体对象和实体对象的属性和域,与数据表及数据字段进行映射(如图4-2-3)。DataBindObject的这种映射机制,可以不必事先声明DataSet构架,当数据结构发生变动时,只需修改相应的业务实体。

None.gif [TableMapping( " Shippers " )]
None.gif
public   class  Shipper:DataBindObject
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    [ColumnMapping(
"ShipperID", IsPrimaryKey=true, AutoIncrement=true)]
InBlock.gif    
protected int pshipperID;
InBlock.gif    
protected string pcompanyName;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public Shipper():base()dot.gif{}
InBlock.gif
InBlock.gif    [ColumnMapping(
"CompanyName")]
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public string CompanyNamedot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
getdot.gif{return pcompanyName;}
ExpandedSubBlockStart.gifContractedSubBlock.gif        
setdot.gif{pcompanyName = value;}
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public int ShipperIDdot.gif{getdot.gif{return pshipperID;}}
ExpandedBlockEnd.gif}

None.gif

 图 4-2-3 DataBindObject的特性声明


(3)Blob字段
在数据库中,某些数据字段可能是大型文本或者二进制数据,当一个业务实体数据加载的时候,我们并不希望对其进行一次性加载,仅在需要的时候在加载该字段内容。Snake.Net框架引入Blob字段,实现这项功能。
Snake.Ne框架可以通过两种途径实现这项功能。可以在DataSet定义中为数据列定义添加msprop:Blob="true"属性,也可以将ColumnMappingAttribute特性中的BLOBColumn属性设置为true(图 4-3-1)。

None.gif [ColumnMapping( " Picture " , BLOBColumn = true )]
None.gif
public   byte [] Picture
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
getdot.gif{return ppicture;}
ExpandedSubBlockStart.gifContractedSubBlock.gif    
setdot.gif{ppicture = value;}
ExpandedBlockEnd.gif}

None.gif

4-3-1 BLOBColumn的属性

(4)关联(Association)与聚合(Aggregation)
关联(Association)是指一个业务实体类指向另一个业务实体类的属性。
聚合(Aggregation)是关联关系的一种,是一种强的关系表示。聚合表示的是整体与部分关系。
以Northwind数据库为例,我们假设订单对象(Order)与消费者对象(Customer)之间通过CustomerID存在关联关系。而订单对象(Order)与订单明细对象(OrderDetail)之间就是聚合关系,通过OrderID进行关联。
Order与Customer对象应该是相对独立的,一个Customer业务实体被加载的时候,并不会去处理对应的Order业务实体。而Order和OrderDetail对象则表现为整体与部分的关系,一个Order业务实体载入时其所有关联的OrderDetail对象也将被载入,当一个Order业务实体被删除时,其所有的OrderDetail业务对象也将被删除。
Snake.Net框架可以使用DataRelation描述数据表与数据表之间的关联关系,DataRelation是在DataSet构架中定义的,开发者不需要额外的代码去处理之中关联。当开发者使用DataBindObject对象是,可以使用AssociationAttribute特性声明对象与对象之间的关系(图 4-4-1)。

None.gif [TableMapping( " Products " )]
None.gif
public   class  Product:DataBindObject
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    [Association(
typeof(OrderDetail), "ProductID")]
InBlock.gif    [ColumnMapping(
"ProductID", IsPrimaryKey=true, AutoIncrement=true)]
ExpandedBlockEnd.gif}

None.gif

图 4-4-1 Association声明

Snake.Net框架使用AggregationAttribute、RetrievedAggregationAttribute和DeletedAggregationAttribute三种特性声明实体对象之间的聚合关系。Snake.Net的聚合分为三种,分别是完全聚合(相当于接受聚合和删除聚合的叠加)、接受聚合(接受一个业务实体对象时,会同时接受其所关联的业务对象)和删除聚合(删除一个业务实体对象时,同时删除其所关联的所有业务对象(图 4-4-2)。

None.gif [Aggregation( typeof (OrderDetail))]
None.gif[TableMapping(
" Orders " )]
ExpandedBlockStart.gifContractedBlock.gif
public   class  Order:DataBindObject dot.gif {}
None.gif

图 4-4-2 Aggregation声明

 (5)继承
继承是对象的重要特性之一,使用继承可以在很大程度上简化开发的过程。在ORM系统中,我们可以把继承对象定义为:与父类使用同一张数据表,每数据行包括一个或多个具有特定值的数据列,以区分与其它基于其父类的继承类。
Snake.Net框架通过声明LimitedColumnAttribute特性,设置子类的特定数据列的值,实现继承功能。


 

转载于:https://www.cnblogs.com/soulroom/archive/2005/11/14/276345.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值