如何在 NHibernate 实体之间创建三向关系?
Posted
技术标签:
【中文标题】如何在 NHibernate 实体之间创建三向关系?【英文标题】:How to create a 3-way relationship between NHibernate entities? 【发布时间】:2015-05-06 05:29:33 【问题描述】:我有以下 NHibernate 实体类:
public class ProductPrice
private long _id;
private long _price; //Let's not get side-tracked by the type
private Currency _currency;
//Just showing for completeness; the link beween ProductPrice and Currency
//is working correctly
public class Currency
private long _id;
private String _threeLetterCode; //INR, USD, GBP, OMR etc.
private String _displayName;
private IList<ProductPrice> _productPrices = new List<ProductPrice>();
public class Item
private long _id;
private String _name;
private IList<ProductPrice> _prices = new List<ProductPrice>();
public class Customer
private long _id;
private String _name;
private IList<ProductPrice> _prices = new List<ProductPrice>();
我想创建一个单独的映射表来链接元组(Customer, Item,
ProductPrice)
,因为我们希望能够以不同的价格提供相同的商品
给不同的客户。 Currency
到 ProductPrice
是一个简单的
一对多的关系。
我不知道如何在 .hbm.xml 文件中映射它。
到目前为止,我有(只做部分映射):
<class name="Item" table="Items">
<id name="ID">
<generator class="native" />
</id>
<property name="Name" />
<bag name="Prices" table="PriceList" inverse="true" cascade="none" lazy="false">
<key column="ItemID" />
<many-to-many class="ProductPrice" column="PriceID" />
</bag>
</class>
和
<class name="ProductPrice" table="ProductPrices" lazy="true">
<id name="ID">
<generator class="native" />
</id>
<property name="Price" />
<many-to-one name="Currency" class="Currency" column="CurrencyID" />
</class>
这仅映射(Item, ProductPrice)
,但即使这样也不会导致进入
当我创建一个新的ProductPrice
时保存在PriceList
表中,将其添加到
一个Currency
,将它添加到一个新的Item
,然后保存Item
和Currency
。
所以我的问题是:
-
我错过了什么?
-
如何确保在
PriceList
表中创建条目时,我
创建ProductPrice
,将其添加到Item
并保存Item
?
(Item, ProductPrice)
映射扩展为三路
(Customer, Item, ProductPrice)
映射?
我该怎么做才能在PriceList
表中有多个相同的(Customer, Item,
ProductPrice)
行(ProductPrice
有效
日期(此处未显示)以便能够提供短期特价)?
版本 2:
我有以下 NHibernate 实体类:
public class ProductPrice
private long _id;
private long _price; //Let's not get side-tracked by the type
private Currency _currency;
private IList<Item> _items = new List<Item>();
//Just showing for completeness; the link beween ProductPrice and Currency
//is working correctly
public class Currency
private long _id;
private String _threeLetterCode; //INR, USD, GBP, OMR etc.
private String _displayName;
private IList<ProductPrice> _productPrices = new List<ProductPrice>();
public class Item
private long _id;
private String _name;
private IList<ProductPrice> _prices = new List<ProductPrice>();
public class Customer
private long _id;
private String _name;
private IList<ProductPrice> _prices = new List<ProductPrice>();
我想创建一个单独的映射表来链接元组(Customer, Item,
ProductPrice)
,因为我们希望能够以不同的价格提供相同的商品
给不同的客户。 Currency
到 ProductPrice
是一个简单的
一对多的关系。
我不知道如何在 .hbm.xml 文件中映射它。
到目前为止,我有(只做部分映射):
<class name="Item" table="Items">
<id name="ID">
<generator class="native" />
</id>
<property name="Name" />
<bag name="Prices" table="PriceList" inverse="true" cascade="save-update" lazy="false">
<key column="ItemID" />
<many-to-many class="ProductPrice" column="PriceID" />
</bag>
</class>
和
<class name="ProductPrice" table="ProductPrices" lazy="true">
<id name="ID">
<generator class="native" />
</id>
<property name="Price" />
<many-to-one name="Currency" class="Currency" column="CurrencyID" />
<bag name="Items" table="PriceList" >
<key column="PriceID" />
<many-to-many class="Item" column="ItemID" />
</bag>
</class>
这仅映射(Item, ProductPrice)
,但即使这样也不会导致进入
当我创建一个新的ProductPrice
时,将其保存在PriceList
表中,将其添加到
一个Currency
,添加到一个新的Item
,然后保存Item
和Currency
。
所以我的问题是:
-
我错过了什么?
-
如何确保在
PriceList
表中创建条目
创建ProductPrice
,将其添加到Item
并保存Item
?
(Item, ProductPrice)
映射扩展为三路
(Customer, Item, ProductPrice)
映射?
我该怎么做才能在PriceList
表中有多个相同的(Customer, Item,
ProductPrice)
行(ProductPrice
有效
日期(此处未显示)以便能够提供短期特价)?
更新 1
将Item
的列表添加到ProductPrice
并更新ProductPrice.hbm.xml
。
更新 2
解决这个问题的一种简单的方法是定义一个实体PriceLink
像这样:
public class PriceLink
protected virtual long ID get; set;
public virtual Customer Cust get; set;
public virtual Item Item get; set;
public virtual ProductPrice ProdPrice get; set;
并像这样映射它:
<class name="PriceLink">
<id name="ID">
<generator class="native" />
</id>
<many-to-one name="Cust" class="Customer" column="CustomerID" />
<many-to-one name="Item" class="Item" column="ItemID" />
<many-to-one name="ProdPrice" class="ProductPrice" column="ProductPriceID" />
</class>
但是,有了这个解决方案,我失去了(我认为)NHibernate 的所有功能 检索整个对象图的能力。这种贫民区解决方案值得吗?
更新 3
这就是我在一个单元中保存实体的方式(在我尝试 PriceLink
之前)
测试(是的,我意识到这是 hack-y 代码,我没有使用事务):
Currency curr = new Currency DisplayName = "XYZ Currency", ThreeLetterCode = "XYZ" ;
ProductPrice prodPrice = new ProductPrice SalePrice = 10000, ValidFrom = DateTimeOffset.MinValue, ValidUpto = DateTimeOffset.MaxValue ;
Item item = new Item Name = "Item 1";
//PriceLink pl = new PriceLink();
using (ISession session = NHibernateHelper.OpenSession())
prodPrice.Currency = curr;
curr.ProductPrices.Add(prodPrice);
//pl.Item = item;
//pl.ProdPrice = prodPrice;
prodPrice.Items.Add(item);
item.Prices.Add(prodPrice);
session.Save(curr);
session.Save(item);
//session.Save(pl);
【问题讨论】:
【参考方案1】:考虑您希望访问数据存储的项目。换句话说,与其将所有项目捆绑在一起,不如考虑根聚合。
在所描述的模型中,您可能需要考虑仅使用货币类,而无需从货币对 productprices 的引用。
虽然用户故事可能首先驱使您这样做,但模型会变得更简单一些,不确定吗?
话虽如此,我不希望 nhibernate 如此强大来检索所有整个对象图,而是选择这些图中的多个。就像具有价格的产品和另一个用户故事一样,您可能希望将货币作为聚合根。
【讨论】:
以上是关于如何在 NHibernate 实体之间创建三向关系?的主要内容,如果未能解决你的问题,请参考以下文章