Developer Safe Bidirectional Relationships with NHibernate

I know how to map bidirectional relationships with NHibernate, but does anyone know an effective method to make them "safe for developers."

What I mean is that as soon as one end of the relationship is established, the other end must be set, for example:

[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); } 

How to achieve this without making the code terribly complicated, as well as supporting NHibernate?

+4
source share
3 answers

One side:

 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); } } 

Many sides:

 class ProductOption { Product _Product; public virtual Product Product { get { return _Product; } set { _Product = value; _Product.AddOptionInternal(this); } } } 

Mapping:

 <class name="Product"> ... <bag name="Options" access="field.pascalcase-underscore"> ... <class name="ProductOption"> ... <many-to-one name="Product" access="field.pascalcase-underscore"/> 

Removing options from the collection (on both sides) remains as an exercise :-)

+4
source

Diego's solution is excellent, but I prefer this template:

One side:

 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; } } } 

Many sides:

 public class ProductOption { Product _product; public virtual Product Product { get { return _product; } set { _product = value; _product.AddOption(this); } } } 
+2
source

Check out this article specifically addressing this issue. The guidance here is very valuable in order to keep such relationships clean by encapsulating the collection operations in your domain model.

0
source

Source: https://habr.com/ru/post/1333640/


All Articles