Castle ActiveRecord(四) 映射基础之一
通过前面几篇文章的介绍,相信大家对ActiveRecord已经是管中窥豹。从这篇文章开始,我们将进入比较实质性的内容。在进入实际的映射之前,先让我们系统地介绍一下前面讲过的东西。
这里的内容都参考自Hibernate、NHibernate的文档及ActiveRecord的文档,大家不妨多参考一下,以免这里叙述有误。若发现错误之处,欢迎指正!
1、类(class)
每个类必须继承ActiveRecordBase 且必须使用 ActiveRecord特性.
public class Blog : ActiveRecordBase
{
}
如果类与之对应的表同名,则表名可以省略:
public class Blog : ActiveRecordBase
{
}
更加详细的信息如下表所示:
|
|
|
|
|
|
|
|
识别器字段名,读写 |
|
识别器字段类型,读写 |
|
识别器字段的值,读写 |
|
是否延时加载,booel类型 |
|
把一个代理类型同目标类型联系起来,该类型在延时装载的时候将作为代理使用 |
|
schema的名称,可读写 |
|
所对应的表名,可读写,如ActiveRecord("Blogs")] [ActiveRecord(Table="Blogs")] |
|
TypeId (inherited from Attribute) |
当在一个派生类中被实现时,为本属性获取一个唯一的标识符 |
附加的where语句 |
2、主键(Primary key):
public class Blog : ActiveRecordBase
{
private int id;
[PrimaryKey]
public int Id
{
get { return id; }
set { id = value; }
}
}
这和下面是一样的:
public int Id
{
get { return id; }
set { id = value; }
}
public int Id
{
get { return id; }
set { id = value; }
}
主键特性的更加详细的信息如下表所示:
Access (inherited from WithAccessAttribute) |
|
AccessString (inherited from WithAccessAttribute) |
|
主键字段名称 |
|
主键字段类型 |
|
CustomAccess (inherited from WithAccessAttribute) |
|
是一个.NET类的名字,也就是主键的生成方式,用来为该持久化类的实例生成唯一的标识,使用方法如:PrimaryKeyType.Native,Native就是一个Generator。Generator有很多内置实现,见表《主键的生成方式》 |
|
主键字段长度 |
|
Params |
Params用来提供Generator所需要的配置参数,这些参数用逗号分割 |
当主键的生成方式为Sequence时,对应的序列的名称,如: PrimaryKey(PrimaryKeyType.Sequence, SequenceName="seqname") |
|
TypeId (inherited from Attribute) |
When implemented in a derived class, gets a unique identifier for this Attribute. |
用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况 和已经在先前的session中保存或装载的脱管(detached)实例区分开来。 (undefined指明使用标识属性值进行判断。) |
主键的生成方式(Generator的内置实现):
Identity |
对DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的内置标识字段提供支持。 返回的标识符是自增的long, short 或者int类型。 |
Sequence |
在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的标识符是自增的long, short或者 int类型。 |
|
使用一个高/低位算法高效的生成long, short 或者 int类型的标识符。 |
SeqHiLo |
使用一个高/低位算法来高效的生成long, short 或者 int类型的标识符,给定一个数据库序列(sequence)的名字。 |
UuidHex |
产生一个byte[] ,把它转换成字符串作为标识符 |
UuidString |
用System.Guid算法生成字符串类型的标识符 |
Guid |
在MS SQL Server 和 MySQL 中使用数据库生成的GUID字符串 |
GuidComb |
用Jimmy Nilsso的一个算法产生一个新的System.Guid |
Native |
根据底层数据库的能力选择identity, sequence 或者hilo中的一个。 |
Assigned |
应用程序自己为对象分配一个标示符。 |
Foreign |
使用外部相关联的对象的标识符。 |
3、联合主键(Composite Keys)
联合主键的使用有点麻烦,首先需要定义一个联合主键类(composite key class),然后在需要使用联合主键的类中添加一个联合主键类(composite key class)类型的属性,并对该属性加以主键特性(PrimaryKey attribute)。如下所示:
[CompositeKey, Serializable]
public class MyCompositeKey
{
private string _keyA;
private string _keyB;
[KeyProperty]
public virtual string KeyA
{
get { return _keyA; }
set { _keyA = value; }
}
[KeyProperty]
public virtual string KeyB
{
get { return _keyB; }
set { _keyB = value; }
}
public override string ToString()
{
return string.Join( ":", new string[] { _keyA, _keyB } );
}
public override bool Equals( object obj )
{
if( obj == this ) return true;
if( obj == null || obj.GetType() != this.GetType() ) return false;
MyCompositeKey test = ( MyCompositeKey ) obj;
return ( _keyA == test.KeyA || (_keyA != null && _keyA.Equals( test.KeyA ) ) ) &&
( _keyB == test.KeyB || ( _keyB != null && _keyB.Equals( test.KeyB ) ) );
}
public override int GetHashCode()
{
return _keyA.GetHashCode() ^ _keyB.GetHashCode();
}
}
使用联合主键的类:
public MyCompositeKey ID
{
get { return _key; }
set { _key = value; }
}
4、属性(Properties)
下面演示了如何名称与对应的列同名的普通属性:
public String Name
{
get { return name; }
set { name = value; }
}
否则你必须指定列名:
public String Name
{
get { return name; }
set { name = value; }
}
可以指定更详细的信息:
public String Name
{
get { return name; }
set { name = value; }
}
这些信息主要如下表:
Access (inherited from WithAccessAttribute) |
可选 - 默认值为 property): Hibernate用来访问属性值的策略。 |
AccessString (inherited from WithAccessAttribute) |
|
所对应的列(字段) |
|
列(字段)的类型 |
|
CustomAccess (inherited from WithAccessAttribute) |
|
(可选): 一个SQL表达式,定义了这个计算 (computed) 属性的值。计算属性没有和它对应的数据库字段 |
|
(可选 - 默认为 true) : 表明用于UPDATE 和/或 INSERT 的SQL语句中是否包含这个被映射了的字段。 |
|
字段长度 |
|
能否为空,Boolean类型 |
|
TypeId (inherited from Attribute) |
When implemented in a derived class, gets a unique identifier for this Attribute |
是否唯一(唯一性约束),可选,Boolean类型 |
|
用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况 和已经在先前的session中保存或装载的脱管(detached)实例区分开来。 (undefined指明使用标识属性值进行判断。) |
|
(可选 - 默认为 true) : 表明用于UPDATE 和/或 INSERT 的SQL语句中是否包含这个被映射了的字段。 |
5、Fields
使用[Field] 特性可以直接映射field。Field的映射与属性是一样的,如:
private String _name;
或:
private String _name;
Field的更加详细的信息的指定方法与property相同,这里不再赘述。
当field的数据在一个internal 类(在.NET组件级别,你可以把它视为public,而在外部则为private)中使用的时候,可以使用field映射。通常,properties比field更可取。
6、Nested (嵌套)
可以使用一个集合类(aggregate class)来映射同一个表的数据,例如:
public class Company : ActiveRecordBase
{
private PostalAddress _address;
[Nested]
public PostalAddress Address
{
get { return _address; }
set { _address = value; }
}
}
public class PostalAddress
{
private String _address;
private String _city;
private String _state;
private String _zipcode;
public PostalAddress()
{
}
public PostalAddress(String address, String city,
String state, String zipcode)
{
_address = address;
_city = city;
_state = state;
_zipcode = zipcode;
}
[Property]
public String Address
{
get { return _address; }
set { _address = value; }
}
[Property]
public String City
{
get { return _city; }
set { _city = value;}
}
[Property]
public String State
{
get { return _state; }
set { _state = value; }
}
[Property]
public String ZipCode
{
get { return _zipcode; }
set { _zipcode = value; }
}
}
NestedAttribute的属性如下表所示:
Update |
表明在用于UPDATE 的SQL语句中是否包含这个字段。默认为true |
Insert |
表明在用于INSERT的SQL语句中是否包含这个字段。默认为true |
|
7、Version/Timestamp (版本/时间戳)
在ActiveRecord也可以使用Nhibernate的Version和Timestamp。Version表明表中包含附带版本信息的数据,这在你准备使用 长事务(long transactions)的时候特别有用。Timestamp指明了表中包含时间戳数据,用来作为版本的替代。
版本:
public Int32 Version
{
get { return version; }
set { version = value; }
}
时间戳:
public Int32 Timestamp
{
get { return ts; }
set { ts = value; }
}
版本的属性如下表所示:
Access (inherited from WithAccessAttribute) |
NHibernate用于访问属性值的策略 |
AccessString (inherited from WithAccessAttribute) |
|
指定持有版本号的字段名 |
|
CustomAccess (inherited from WithAccessAttribute) |
|
版本号的类型 |
|
TypeId (inherited from Attribute) |
|
时间戳的属性如下所示:
Access (inherited from WithAccessAttribute) |
NHibernate用于访问属性值的策略 |
AccessString (inherited from WithAccessAttribute) |
|
持有时间戳的字段名 |
|
CustomAccess (inherited from WithAccessAttribute) |
|
TypeId (inherited from Attribute) |
|
一个脱管(detached)实例的version或timestamp不能为空(null),因为NHibernate不管 unsaved-value指定为何种策略,它将分离任何属性为空的version或timestamp 实例为瞬时(transient)实例。 避免NHibernate中的传递重附(transitive reattachment)问题的一个简单方法是 定义一个不能为空的version或timestamp属性,特别是在人们使用程序分配的标识符(assigned identifiers) 或复合主键时非常有用!