我知道如何使用NHibernate映射双向关系,但是有没有人知道一种有效的技术来让他们'开发人员安全'。
我的意思是,只要关系的一端建立,另一端也应该设置,例如:
[Test]
public void TestBidirectionalRelationships_WhenAddingOptionToProduct()
{
var product = new Product();
var productOption = new ProductOption();
product.AddOption(productOption);
Assert.That(product.Options.Contains(productOption));
Assert.That(productOption.Product, Is.EqualTo(product);
}
[Test]
public void TestBidirectionalRelationships_WhenSettingProductOnOption()
{
/* Alternatively, productOption.Product would have no public setter */
var product = new Product();
var productOption = new ProductOption();
productOption.Product = product;
Assert.That(product.Options.Contains(productOption));
Assert.That(productOption.Product, Is.EqualTo(product);
}
如何在不使代码变得非常复杂的情况下实现这一目标,同时保持NHibernate的快乐?
答案 0 :(得分:4)
一方:
class Product
{
public Product()
{
_Options = new List<ProductOption>();
}
ICollection<ProductOption> _Options;
public virtual IEnumerable<ProductOption> ProductOptions
{
get { return _Options.Select(x => x); }
}
public virtual AddOption(ProductOption option)
{
option.Product = this;
}
protected internal virtual AddOptionInternal(ProductOption option)
{
_Options.Add(option);
}
}
许多方面:
class ProductOption
{
Product _Product;
public virtual Product Product
{
get { return _Product; }
set
{
_Product = value;
_Product.AddOptionInternal(this);
}
}
}
映射:
<class name="Product">
...
<bag name="Options" access="field.pascalcase-underscore">
...
<class name="ProductOption">
...
<many-to-one name="Product" access="field.pascalcase-underscore"/>
从集合中删除选项(从任何一方)留作练习: - )
答案 1 :(得分:2)
迭戈的解决方案很好,但我更喜欢这种模式:
一方:
public class Product
{
private IList<ProductOption> _options;
public Product()
{
_options = new List<ProductOption>();
}
public virtual IEnumerable<ProductOption> ProductOptions
{
get { return _options; }
}
public virtual AddOption(ProductOption option)
{
// equality must be overridden for this to work
// Check contains to break out of endless loop
if (!_options.Contains(options))
{
_options.Add(option);
option.Product = this;
}
}
}
许多方面:
public class ProductOption
{
Product _product;
public virtual Product Product
{
get { return _product; }
set
{
_product = value;
_product.AddOption(this);
}
}
}
答案 2 :(得分:0)
查看专门解决此问题的this article。这里的指导非常有价值,可以通过将收集操作封装在域模型中来保持这种关系的清洁。