找回密码
 立即注册
首页 业界区 业界 NHibernate拾贝1255:联合主键(composite-id)

NHibernate拾贝1255:联合主键(composite-id)

遇玷 2025-5-29 14:57:46
本节内容
           
  • 概览       
  • 实例       
  • 参考资料
概览

这个系列是以博客形式整理关于NHibernate的Issues。记录一些零碎的小例子,通过零零碎碎的整理,可以巩固自己的知识和扩展我们的知识面。这些小例子也可以适当的在项目中呈现。
这次看看联合主键(composite-id)。
实例

有时建模需要,需要把几个属性组合了一个标识符,就用到了联合主键(composite-id),我们使用它,就难免遇到了一些问题,比如如何映射,如何等同性比较,如何查询等操作。
1.Domain

这里定义一个Domain——CustomerValue,这个持久化类有两个属性:联合主键(composite-id)和Value。
我们使用联合主键,首先需要定义联合主键的类型,同时这个类必须重载Equals()和GetHashCode()方法,来实现组合的标识符等同性判断。 例如下面的CustomerValue持久化类,其联合主键类型为CustomerValueId,就是Customer持久化类与int类型的复合形式,在CustomerValueId类中重载了Equals()和GetHashCode()方法。
  1. public class Customer
  2. {
  3.     public virtual int Id { get; set; }
  4.     public virtual string Name { get; set; }
  5. }
  6. public class CustomerValue
  7. {
  8.     public virtual CustomerValueId Id { get; set; }
  9.     public virtual decimal Value { get; set; }
  10. }
  11. public class CustomerValueId : IEquatable<CustomerValueId>
  12. {
  13.     private int? _requestedHashCode;
  14.     public Customer Customer { get; set; }
  15.     public int CustomKey { get; set; }
  16.     public bool Equals(CustomerValueId other)
  17.     {
  18.         if (ReferenceEquals(null, other))
  19.         {
  20.             return false;
  21.         }
  22.         if (ReferenceEquals(this, other))
  23.         {
  24.             return true;
  25.         }
  26.         return Equals(other.Customer, Customer) && other.CustomKey == CustomKey;
  27.     }
  28.     public override bool Equals(object obj)
  29.     {
  30.         if (ReferenceEquals(null, obj))
  31.         {
  32.             return false;
  33.         }
  34.         if (ReferenceEquals(this, obj))
  35.         {
  36.             return true;
  37.         }
  38.         if (obj.GetType() != typeof(CustomerValueId))
  39.         {
  40.             return false;
  41.         }
  42.         return Equals((CustomerValueId)obj);
  43.     }
  44.     public override int GetHashCode()
  45.     {
  46.         if (!_requestedHashCode.HasValue)
  47.         {
  48.             unchecked
  49.             {
  50.                 _requestedHashCode =
  51.                  ((Customer != null ? Customer.GetHashCode() : base.GetHashCode()) * 397) ^ CustomKey;
  52.             }
  53.         }
  54.         return _requestedHashCode.Value;
  55.     }
  56. }
复制代码
2.Mapping

需要对两个Domain映射,这里注重理解下联合主键的映射,这里是把类的Customer属性和CustomerKey属性组合成为标识符属性。节点用于映射子元素,一般都是Domain(多对一关系的);节点用于映射属性。在这里我需要在节点中设置not-found attribute来避免在运行时抛出异常,就是设置not-found="ignore"。
  1. <class name="Customer">
  2.     <id name="Id">
  3.         <generator class="hilo" />
  4.     </id>
  5.     <property name="Name" />
  6. </class>
  7. <class name="CustomerValue" >
  8.     <<strong>composite-id name="Id" class="CustomerValueId">
  9.         <key-many-to-one name="Customer" column="CustomerId" not-found="ignore" />
  10.         <key-property name="CustomKey" />
  11.     </composite-id</strong>>
  12.     <property name="Value" />
  13. </class>
复制代码
3.Test

做完了上面的步骤,测试一下,保存一个CustomerValue。查询验证下并删除。这个测试很简单,就不贴出SQL结果了。
  1. using (var session = OpenSession())
  2. {
  3.     using (var tx = session.BeginTransaction())
  4.     {
  5.         var customer = new Customer { Name = "李永京" };
  6.         session.Save(customer);
  7.         var customerValue = new CustomerValue
  8.                                 {
  9.                                     Id = new CustomerValueId { Customer = customer, CustomKey = 20012 },
  10.                                     Value = 1255.0m
  11.                                 };
  12.         session.Save(customerValue);
  13.         tx.Commit();
  14.     }
  15.     using (var tx = session.BeginTransaction())
  16.     {
  17.         var customerValue = session.CreateQuery("from CustomerValue c where c.Value=:value")
  18.             .SetDecimal("value", 1255.0m)
  19.             .UniqueResult<CustomerValue>();
  20.         session.Delete(customerValue);
  21.         session.Delete("from Customer");
  22.         tx.Commit();
  23.     }
  24. }
复制代码
参考资料

NHibernate Forge:NHibernate Reference Documentation(在线NHibernate参考文档5.1.5节composite-id介绍)
Adam Aldrich:Nhibernate Session.Get using a Composite Id(我们使用联合主键之后如何用ISession.Get(object id)方法查询这个Domain呢?)

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册