您的位置:首页 > 移动开发

NHibernate文档翻译---使用AttributesNHibernate.Mapping.Attributes

2012-05-27 13:44 465 查看
目录

如何使用?提示已知的问题和TODOs开发者须知

什么是 NHibernate.Mapping.Attributes?

NHibernate.Mapping.Attributes 是 NHibernate 的附加软件,它是Pierre Henri Kuat (aka KPixel)贡献的; 以前的实现者是 John Morris.NHibernate需要映射信息来绑定你的域对象到数据库。通常他们被写在(并且被保存在)在分散的hbm.xml文件里。

使用NHibernate.Mapping.Attributes,你可以使用.NET属性(attributes)来修饰你的实体和被用于产生.hbm.xml映射(文件或者流)的属性(attributes)。因此,你将不再会为这些令人厌恶的文件而烦恼。

这个库里面的内容包括。

NHibernate.Mapping.Attributes: 你需要的唯一工程(作为最终用户)

Test:一个使用属性(attributes)和HbmSerializer的简单用例,是NUnit的TestFixture

Generator: 用来产生属性(attributes) 和HbmWriter的程序.

Refly : 感谢Jonathan de
Halleux 提供这个库,它使得产生代码变得如此简单.

重要提示

这个库是使用文件
/src/NHibernate.Mapping.Attributes/nhibernate-mapping-2.0.xsd
(它嵌入在程序集中能够检查产生的XML流的合法性)产生的.这个文件可能在NHibernate每次发布新版本时发生变化,所以你应该在不同的版本中使用它时,重新生成它(打开Generator工程,编译并且运行Generator项目).但是,在0.8之前的版本中它并没有通过测试.

如何使用?

最终用户类 是
NHibernate.Mapping.Attributes.HbmSerializer
.这个类序列化你的域模型到映射流.你可以逐个序列化程序集中的类.
NHibernate.Mapping.Attributes.Test
可以作为参考.

第一步用属性(attributes)修饰你的实体;你可以用
[Class]
,
[Subclass]
,
[JoinedSubclass]
或者
[Component]
.然后,修饰成员(字段/属性properties);它们能够代替很多映射中需要使用的属性(attributes
),例如:

[NHibernate.Mapping.Attributes.Class]
public class Example
{
[NHibernate.Mapping.Attributes.Property]
public string Name;
}


完成这个步骤后,使用
NHibernate.Mapping.Attributes.HbmSerializer
:(这里我们使用了Default ,它是一个实例,在你不必须/不想自己创建它时使用).

System.IO.MemoryStream stream = new System.IO.MemoryStream(); // where the xml will be written
NHibernate.Mapping.Attributes.HbmSerializer.Default.Validate = true; // Enable validation (可选)
// Here, we serialize all decorated classes (but you can also do it class by class)
NHibernate.Mapping.Attributes.HbmSerializer.Default.Serialize(
stream, System.Reflection.Assembly.GetExecutingAssembly() );
stream.Position = 0; // Rewind
NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
cfg.Configure();
cfg.AddInputStream(stream); // Use the stream here
stream.Close();
// Now you can use this configuration to build your SessionFactory...

注意

正如你所见:

NHibernate.Mapping.Attributes是没有(真正的)侵入性的.在你的对象上设置属性(attributes ),不会强迫你在NHibernate 使用它们,并且不会破坏你的架构体系中的任何约束.属性(Attributes)仅仅是纯粹的信息.

提示

使用
HbmSerializer.Validate
来启用/禁用产生的xml流的合法性检查(依靠NHibernate mapping schema);对于快速查找问题这是很有用的(它们被StringBuilder写入
HbmSerializer.Error
).如果错误是这个库预期的,库会看它是否是已知的问题并且报告它;解决这些问题能帮助你完成你的解决方案. :)

你的类,字段和属性properties(成员)可以是私有的;请确认你有使用反射访问私有成员的权限(
ReflectionPermissionFlag.MemberAccess
).

映射类的成员也会在基类中查找(直到找到映射的基类).因此,你可以在基类(没有做映射)中修饰成员,然后在它的(做过映射的)子类中使用它.

对于一个有类型(
System.Type
)的Name,使用Name="xxx"(作为string)设置类型或者设置NameType=typeof(xxx);(给 "Name"添加"类型")

默认情况下,.NET属性(attributes)没有维持属性(attributes)的顺序;因此,你必须自己设置顺序,在你管理顺序的时候(使用每个属性的第一个参数).强烈推荐设置它,当你的一个成员上有超过一个属性(attribute )时.

只要不产生含糊,你可以在成员上定义很多不相干的属性(attributes).一个好的例子是在标识符成员上的类描述(class-related)属性(attributes )(类似鉴别器
<discriminator>
).但是不要忘记管理顺序(
<discriminator>
必须在
<id>
的后面).顺序来自NHibernate mapping
schema中元素(elements)的顺序.在我个人看来,我更喜欢在属性上使用负数(如果它们是在前面的!).

你可以在类上面加
[HibernateMapping]
来指定
<hibernate-mapping>
属性(attributes)(当类被序列化成流时使用).你也可以使用
HbmSerializer.Hbm*
属性(properties)(当被
[HibernateMapping]
修饰的类型或程序集被序列化时被使用).

不使用一个字符串作为鉴别器值(
DiscriminatorValue
)(在
[Class]
[Subclass]
),你可以在任何你需要的对象上这样使用.例子:

[Subclass(DiscriminatorValueEnumFormat="d", DiscriminatorValueObject=DiscEnum.Val1)]


在这里,对象是一个枚举,你可以设置你需要的格式(默认的值是"g").注意你必须把它放在前面!对于其他的类型,只是简单的使用了对象的
ToString()
方法.

如果你使用
Nullables.NullableXXX
类型的的成员(在库Nullables中),系统会自动映射到
Nullables.NHibernate.NullableXXXType
;不用在
[Property]
中设置
Type="..."
(让它为空).感谢Michael
Third的这个主意. :)

NHibernate.Mapping.Attributes产生的每个流都有一个产生日期的注释;你可以通过方法
WriteDateComment
启用/禁用它.

如果你忘记提供一个必须的xml属性(attribute),系统会抛出一个异常,在创建映射时.

映射
[Component]
时,被推荐的并且最简单的方式是使用
[ComponentProperty]
.

首先,放置
[Component]
在组件类并且映射它的字段/属性.注意不要在
[Component]
设置名字.然后,在你的类的每个成员,添加
[ComponentProperty]
.但是你不能改变每个成员的存取(
Access
),更新(
Update
)或插入(
Insert
).

在NHibernate.Mapping.Attributes.Test里有一个例子(注意
CompAddress
类和他在其他类中的使用).

注意最后一件事情:
ComponentPropertyAttribute
是从
DynamicComponentAttribute
继承来的,容易把它紧接着写在
<component>
元素的后面,在XML流中.

另一个映射
[Component]
的方式是,它用这种方法让库工作:如果一个类包含了一个组件映射,那么这个组件将会被类包含.NHibernate.Mapping.Attributes.Test包含
JoinedBaz
Stuff
使用地址(
Address
)组件的例子.

很简单的,添加了以后

[Component(Name = "MyComp")] private class SubComp : Comp {}


在所有类中,一个优势是能够改变每个成员的存取(
Access
),更新(
Update
)或插入(
Insert
).但是,你必须添加组件子类到每个类中(并且它不能被继承).

关于自定义。
HbmSerializer
使用
HbmWriter
序列化各种属性(attributes)。他的方法是虚的;因此你可以创建一个子类,重写任何方法(来改变它的默认行为)。

使用属性(property)
HbmSerializer.HbmWriter
来改变写的实现者。(你可以设置一个
HbmWriter
的子类)。

使用了部分提示的例子:(0,1和2按顺序排列)

[NHibernate.Mapping.Attributes.Id(0, TypeType=typeof(int))] // Don't put it after [ManyToOne] !!!
[NHibernate.Mapping.Attributes.Generator(1, Class="uuid.hex")]
[NHibernate.Mapping.Attributes.ManyToOne(2, ClassType=typeof(Foo), OuterJoin=OuterJoinStrategy.True)]
private Foo Entity;


产生的:

<id type="Int32">
<generator class="uuid.hex" />
</id>
<many-to-one name="Entity" class="Namespaces.Foo, SampleAssembly" outer-join="true" />


已知的问题和TODOs

首先,阅读源代码里面的TODOs

Position
属性(property)被加在所有属性(attributes)上,用来给他们排序。但是仍然有问题:

当一个父元素"p"有一个子元素"x",它的另一个子元素"c"有子元素"x"。:D 如图

<p>
<c>
<x />
</c>
<x />
</p>


在这个例子中,如果这样写:

[Attributes.P(0)]
[Attributes.C(1)]
[Attributes.X(2)]
[Attributes.X(3)]
public MyType MyProperty;


X(3)将会属于C(1)!(和X(2)一样)

下面是
<dynamic-component>
<nested-composite-element>
的情况。

另一个坏消息是,现在,后来加入的XML元素不能被包含.例如:没有办法在
<dynamic-component>
放置集合.原因是
nhibernate-mapping-2.0.xsd
文件告诉程序元素怎么被创建,按照什么顺序被创建,并且NHibernate.Mapping.Attributes按这个顺序使用它们.

总之,解决方案应该添加整型的ParentNode属性(property)给BaseAttribute,这样你能够创建一个真实的情况...

实际上,没有其他的知识点了而且也没有计划好的修改.这个库将会成为稳定的完整版本;但是你发现了问题或者有有效的改进想法,请联系我们!

另一个消息,希望有比NHibernate.Mapping.Attributes.Test更好的TestFixture.:D

开发者须知

schema (
nhibernate-mapping-2.0.xsd
)的任何改变意味着:

检查是否要在Generator中做任何改变(象updating KnowEnums / AllowMultipleValue / IsRoot / IsSystemType / IsSystemEnum / CanContainItself)

更新
/src/NHibernate.Mapping.Attributes/nhibernate-mapping-2.0.xsd
(复制/粘贴),并且再次运行Generator(即使你没有修改)

运行测试项目,确定没有已知的异常抛出.应该在可以确保能够把握改变带来的破坏时,修改/添加这个项目中一个类/属性(property)(=>更新hbm.xml文件和/或
NHibernate.Mapping.Attributes-1.1.csproj
项目的引用)

这个实现基于NHibernate mapping schema;有可能很多"标准schema特性"没有被支持...

这个版本的NHibernate.Mapping.Attributes需要使用NHibernate库的版本的schema来产生.

这个项目的设计,性能是一个(十分)小的目标,实现和维护则要重要许多.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: