找回密码
 立即注册
首页 业界区 业界 NHibernate之旅(8):巧用组件之依赖对象

NHibernate之旅(8):巧用组件之依赖对象

猷浮 2025-5-30 01:39:47
本节内容
           
  • 引入       
  • 方案1:直接添加       
  • 方案2:巧用组件       
  • 实例分析       
  • 结语
引入

通过前面7篇的学习,有点乏味了~~~这篇来学习一个技巧,大家一起想想如果我要在Customer类中实现一个Fullname属性(就是Firstname和Lastname的组合)该怎么做呢?
方案1:直接添加

“我知道!修改Customer类,添加一个Fullname属性!即Customer.Fullname!”
“恩,完全正确......”
“这就意味着在Customer类中把Firstname和Lastname两个属性重新修改组合为Fullname属性。这样的话,如果有其它的类(像Vendor、Shiper)使用了Firstname和Lastname两个属性,这就需要修改很多业务逻辑。那你的麻烦可就大了,还有什么方法吗?”
“.........”
方案2:巧用组件

NHibernate中,提供了组件(Component)和动态组件来帮助我们完成这件事情。其实组件在NHibernate中为了不同目的被重复使用。这里我们使用它来依赖对象
映射文件中,元素把子对象的一些属性映射为父类对应的表的一些字段。然后,组件可以定义它们自己的属性、组件或者集合。
下面用两幅图显示组件和动态组件两个节点映射属性:
1.jpeg

看看这些映射属性:
           
  • access(默认property):NHibernate用来访问属性的策略       
  • class(默认通过反射得到的属性类型):组件(子)类的名字       
  • insert:被映射的字段是否出现在SQL的INSERT语句中       
  • name:属性名propertyName       
  • update:被映射的字段是否出现在SQL的UPDATE语句中       
  • 子元素:为组件(子)类的一些属性与表字段之间建立映射       
  • 子元素:在组件类内部就可以有一个指向其容器的实体的反向引用
元素允许一个IDictionary作为组件映射,其中属性名对应字典中的键。这又是使用组件的另一种用法。
知道上面的知识,我们该想想上面的问题该如何利用组件来实现了吧。
实例分析

我们用一幅图来展示我们这节所说的一切:
2.jpeg

开始动手吧!
1.新建Name类
  1. namespace DomainModel.Entities
  2. {
  3.     public class Name
  4.     {
  5.         public string Firstname { get; set; }
  6.         public string Lastname { get; set; }
  7.         public string Fullname
  8.         {
  9.             get
  10.             {
  11.                 return Firstname + " " + Lastname;
  12.             }
  13.         }
  14.     }
  15. }
复制代码
简单的说,这个类用于组合Fullname属性。
2.修改Customer类
  1. namespace DomainModel.Entities
  2. {
  3.     public class Customer
  4.     {
  5.         public virtual int CustomerId { get; set; }
  6.         public virtual int Version { get; set; }
  7.         public virtual Name Name { get; set; }
  8.     }
  9. }
复制代码
修改Customer类,去除原来的Firstname和Lastname属性,添加Name属性。这时Name作为Customer的一个组成部分。需要注意的是:和原来Firstname和Lastname属性一样,需要对Name的持久化属性定义getter和setter方法,但不需要实现任何的接口或声明标识符字段。
3.修改Customer映射
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
  3.                            assembly="DomainModel" namespace="DomainModel">
  4.   <class name ="DomainModel.Entities.Customer,DomainModel" table="Customer">
  5.     <id name="CustomerId" column="CustomerId" type="Int32" unsaved-value="0">
  6.       <generator class ="native"></generator>
  7.     </id>
  8.     <version name="Version" column="Version" type="integer" unsaved-value="0"/>
  9.     <<strong>component name="Name" class="DomainModel.Entities.Name,DomainModel">
  10.         <property name="Firstname" column ="Firstname" type="string"
  11.                              length="50" not-null="false" unique-key="UC_CustomerName"/>
  12.         <property name ="Lastname" column="Lastname" type="string"
  13.                              length="50" not-null="false" unique-key="UC_CustomerName"/>
  14.     </component</strong>>
  15.   </class>
  16. </hibernate-mapping>
复制代码
首先定义Component的一些属性,指定属性名和组件映射的类名。再使用子元素,为Name类的Firstname、Lastname属性与表字段之间建立映射。是不是很简单~~
这时Customer表中还是CustomerId、Version、Firstname、Lastname字段。完全不需要修改数据库表结构哦。
这里需要注意两点:
           
  • 就像所有的值类型一样,组件不支持共享引用。组件的值为空从语义学上来讲是专有的。每当重新加载一个包含组件的对象,如果组件的所有字段为空,那么NHibernate将假定整个组件为空。对于绝大多数目的,这样假定是没有问题的。       
  • 组件的属性可以是NHibernate类型(包括集合、多对一关联以及其它组件)。嵌套组件不应该作为特殊的应用被考虑。NHibernate趋向于支持设计细粒度的对象模型。
4.编写方法

这时,我们需要修改或者重新编写新的方法来实现我们想要的逻辑。
  1. public IList<Customer> ReturnFullName(string firstname, string lastname)
  2. {
  3.     return _session
  4.          .CreateQuery("select from Customer c where c.Name.Firstname=:fn and c.Name.Lastname=:ln")
  5.         .SetString("fn", firstname)
  6.         .SetString("ln", lastname)
  7.         .List<Customer>();
  8. }
复制代码
现在,我们访问Customer的Firstname、Lastname属性,只需要在原来的基础上通过Name访问,例如上面修改的情况,看看上面图片上怎么访问的吧,一目了然。
如果我们要添加一个Customer怎么办呢?代码片段如下所示:
  1. var customer = new Customer() { Name = new Name() { Firstname = "YJing", Lastname = "Lee" } };
复制代码
5.测试方法

有了上面的方法,我们编写一个测试用例测试一下这个方法吧:看看结果测试成功,OK。
  1. [Test]
  2. public void ReturnFullNameTest()
  3. {
  4.     IList<Customer> customers = _relation.ReturnFullName("YJing","Lee");
  5.     foreach (Customer c in customers)
  6.     {
  7.         Assert.AreEqual("YJing Lee", c.Name.Fullname);
  8.     }
  9. }
复制代码
结语

这一篇像大家介绍一个使用组件技巧,通过组件可以改善我们的对象模型,而数据库结构不需要变化。通过这一篇的技巧,利用组件来映射来依赖对象,可以非常连贯的引入NHibernate中的多表映射关系、集合等内容,这些才是NHibernate中的亮点,就连LINQ都比不过它。从下篇开始就来学习NHibernate中的闪光点。
本系列链接:NHibernate之旅系列文章导航
NHibernate Q&A
           
  • 欢迎加入NHibernate中文社区,一起讨论NHibernate知识!       
  • 请到NHibernate中文社区下载本系列相关源码。
下次继续分享NHibernate!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册