2010-12-29 8 views
4

Ich weiß, wie man bidirektionale Beziehungen mit NHibernate abbildet, aber jemand weiß eine effektive Technik, um sie "entwicklungssicher" zu machen.Entwickler-sichere bidirektionale Beziehungen mit NHibernate

Was ich damit meine, ist, dass, sobald ein Ende der Beziehung hergestellt wird, sollte das andere Ende auch eingestellt werden, zum Beispiel:

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

Wie würde man dies erreichen, ohne die Herstellung von Code horrend komplex, und während NHibernate auch glücklich zu halten?

+0

Das hängt davon ab, was du meinst mit „horrend Komplex“ – Paco

Antwort

0

Werfen Sie einen Blick auf this article, die speziell dieses Problem angeht. Die Anleitung hier ist sehr hilfreich, um solche Beziehungen sauber zu halten, indem Sie die Erfassungsvorgänge in Ihrem Domänenmodell einkapseln.

4

Eine Seite:

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

Viele Seite:

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"/> 

Entfernen von Optionen aus der Sammlung (von beiden Seiten) wird als Übung: -)

2

Dieg o Die Lösung ist in Ordnung, aber ich ziehe dieses Muster:

Eine Seite:

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

Viele Seite:

public class ProductOption 
{ 
    Product _product; 

    public virtual Product Product 
    { 
     get { return _product; } 
     set 
     { 
      _product = value; 
      _product.AddOption(this); 
     } 
    } 
} 
+0

Das ist weniger gekoppelt .. Aber ich bin sicher nicht in den Anruf verliebt ;-) –

+0

@Diego - Kannst du erklären warum? Neugierig warum, weil ich manchmal ähnlich mache. – Phill

+0

@Phill, weil es Kosten verursacht, die niedrig sein können, wenn es sich um eine bereits geladene oder speicherinterne kleine Sammlung handelt, moderat, wenn es groß ist, und hoch, wenn es das Laden einer Tasche aus der Datenbank erzwingt. –

Verwandte Themen