Двусторонние отношения, безопасные для разработчика, с NHibernate - PullRequest
4 голосов
/ 29 декабря 2010

Я знаю, как отобразить двунаправленные отношения с 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?

Ответы [ 3 ]

4 голосов
/ 29 декабря 2010

Одна сторона:

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

Удаление опций из коллекции (с любой стороны) оставлено в качестве упражнения: -)

2 голосов
/ 29 декабря 2010

Решение Диего в порядке, но я предпочитаю эту схему:

Одна сторона:

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);
        }
    }
}
0 голосов
/ 29 декабря 2010

Ознакомьтесь с этой статьей , в которой конкретно рассматривается эта проблема.Приведенные здесь рекомендации очень важны для поддержания чистоты таких отношений, инкапсулируя операции сбора в вашей доменной модели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...