三、数据映射
1. 数据表和字段
数据表与字段的映射是ORM的基本特性,通过映射关系将实体对象的类、属性、域与数据表名和字段名建立一一对应的关系。Snake.Net一般将一个实体类映射到特定的数据表,将类的属性或域映射到特定的字段。
a)使用DataSet Schema映射: Snake.Net一般使用DataSet及其包含的各种子对象(DataTable, DataRow等)的ExtendProperty属性,进行映射关系的配置。如下:
<xs:element name="Shippers" msprop:Mapping="Snake.Enterprise.Shipper">
<xs:element name="ShipperID" msdata:AutoIncrement="true" type="xs:int" msprop:Mapping="pshipperID" />
b) 是用Attriute映射:Snake.Net 也可以使用TableMappingAttribute和ColumnMappingAttribute映射,如下:
[TableMapping("Shippers")]
public class Shipper:DataBindEntity
{
protected string pcompanyName;
[ColumnMapping("CompanyName")]
public string CompanyName
{
get{return pcompanyName;}
set{pcompanyName = value;}
}
}
2. 关键字
如果一个属性集能惟一地标识表的一行而又不含多余的属性,那么这个属性集称为侯选关键字。Snake.Net中的关键字可以指定某一或一组属性或域作为为实体的关键字。此外,Snake.Net中关键字可以最为实体的唯一标识用于,应用于数据持久层。
a)使用DataSet Schema映射:系统将根据DataSet中定义的Primary Key自动配置。
b) 是用Attriute映射:Snake.Net 也可以使用ColumnMappingAttribute和KeyColumnMappingAttribute映射。如下:
[ColumnMapping("OrderID", IsPrimaryKey=true, AutoIncrement=true)]
protected int porderID;
protected int porderID;
[KeyColumnMapping ("OrderID", AutoIncrement=true)]
public string CustomerID{
get{return pcustomerID;}
set{ pcustomerID = value;}
}
3. BLOB字段
在数据库中,某些字段数据类型可能是大型文本或者二进制数据。当一个业务实体数据加载的时候,如果同时加载这些数据可能会对性能造成重大影响。Snake.Net引入BLOB声明,避免一次性加载大类型数据,仅在需要的时候在加载该字段数据。在调用时可以使是用BLOBRetrieve加载大类型数据。
a)使用DataSet Schema映射:使用Blob扩展属性设置BLOB字段,如下
<xs:element name="Picture" type="xs:base64Binary" minOccurs="0" msprop:Blob="true" />
b) 是用Attriute映射:Snake.Net可以使用ColumnMapping的BLOBColumn属性将实体属性或域设置为BLOB类型,如下:
[ColumnMapping("Picture", BLOBColumn=true)]
public byte[] Picture
{
get{return ppicture;}
set{ppicture = value;}
}
4. 实体关联(Association)
关联是指一个业务实体类指向另一个业务实体类的属性。Snake.Net通过设置实体之间的关联关系,可以在很大程度上简化查询的操作,Snake.Net可以根据设置的关联关系自动生成实体对象之间关联的SQL语句。
a)使用DataSet Schema映射:Snake.Net根据DataSet中的DataRelation也就是对应DataTable之间的关联关系自动映射到对象。
b) 是用Attriute映射:Snake.Net通过配置AssociationAttribute属性配置对象之间的关联关系。如下:
[Association(typeof(Product), "CategoryID")]
[ColumnMapping("CategoryID", IsPrimaryKey=true, AutoIncrement=true)]
protected int pcategoryID;
5. 实体聚合(Aggregation)
聚合是关联关系的一种,是一种强的关系表示。聚合表示的是整体与部分关系。Snake.Net中的聚合表示实体与实体之间的隶属关系。
Snake.Net可以通过设置聚合关系,在实体对象接受时自动接受聚合子实体;在实体对象删除时,自动删除聚合子实体。Snake.Net提供了三种形式的聚合:完全聚合、接受聚合和删除聚合分别对应AggregationAttribute,RetrievedAggregationAttribute和
DeletedAggregationAttribute属性。如下:
[Aggregation(typeof(OrderDetail))]
[TableMapping("Orders")]
public class Order:DataBindEntity{}
6. 继承与限定
继承是实体的重要特性之一,使用继承可以在很大程度上简化开发的过程。 在Snake.Net系统中,我们可以把继承实体定义为:与父类使用同一张数据表,每数据行包括一个或多个具有特定值的数据列,以区分与其它基于其父类的继承类。
在Snake.Net框架中继承类的定义方法和普通继承类的定义方法一样,需要注意的是父类所有的需要映射的域应当定义为protected, internal 或public不能是用private。
Snake.Net可以通过声明LimitedColumnAttribute特性,设置继承类的某一属性的值为固定值。在接受和查询业务实体的操作中,Snake.Net能够自动添加将限定列的值。
父实体对象AbstractGroup的定义如下:
[Aggregation(typeof(GroupProperty))]
[DeletedAggregation(typeof(GroupUser))]
[TableMapping("t_Group_Base")]
public abstract class AbstractGroup:DataMappingEntity, IGroup
{
protected Guid pid;
protected int ptypeId;
protected string pname;
protected string pdescription;
protected string pappName;
private GroupPropertyCollection _properties;
protected AbstractGroup(string name):this()
{
//check for arguments
if (name == null) throw new ArgumentNullException("name");
pname = name;
}
protected AbstractGroup()
{
_properties = new GroupPropertyCollection(this, GetChildren<GroupProperty>());
}
public Guid Id{get{return (Guid)GetValue(pid);}}
public int TypeId{get{return (int)GetValue(ptypeId);}}
public string Name{
get{return (string)GetValue(pname);}
set{pname = (string)SetValue(pname, value);}
}
public string Description{
get{return (string)GetValue(pdescription);}
set{pdescription = (string)SetValue(pdescription, value);}
}
public IProperties Properties{get{return _properties;}}
protected IList BaseUsers{
get{
using(IEntityManager em
= EntityManager.Create(GetType())){
return em.RetrieveChildren(this, typeof(User));
}
}
}
}
继承实体对象Group的定义如下:
[Alias("Group")]
[LimitedColumn("TypeId", 1)]
public class Group:AbstractGroup
{
public Group(string name):base(name)
{
}
protected Group():base()
{
}
public IList Users{get{return base.BaseUsers;}}