Какова лучшая практика для списков только для чтения в NHibernate - PullRequest
10 голосов
/ 14 марта 2009

Модель предметной области, над которой я работаю, имеет корневой агрегат и дочерние объекты Что-то вроде следующего кода:

class Order
{
   IList<OrderLine> Lines {get;set;}
}

class OrderLine
{
}

Теперь я хочу, чтобы мой ордер контролировал линии. Примерно так:

class Order
{
   OrderLine[] Lines {get;}

   void AddLine(OrderLine line);
}

В настоящее время мы используем следующий шаблон:

class Order
{
   private IList<OrderLine> lines = new List<OrderLine>();
   OrderLine[] Lines {get {return this.lines;}}

   void AddLine(OrderLine line)
   {
      this.orders.Add(line);
   {
}

NHibernate сопоставляется непосредственно с полем линий.

Теперь вопросы ...

  • Что вы практикуете в таких ситуациях?
  • Кто-нибудь использует методы: public IEnumerable GetLines ()
  • Что вы используете в качестве типа возврата для свойства? Может быть ReadOnlyCollection или IEnumerable;
  • Может быть, это не лучшее место, чтобы спросить? Предложите пожалуйста.

Обновление: кажется, IEnumerable выигрывает, однако решение все еще не идеально ...

Ответы [ 5 ]

14 голосов
/ 15 марта 2009

Я делаю это так:

public class Order
{
      private ISet<OrderLine> _orderLines = new HashedSet<OrderLine>();

      public ReadOnlyCollection<OrderLine> OrderLines
      {
          get { return new List<OrderLine>(_orderLines).AsReadOnly(); }
      }

      public void AddOrderLine( OrderLine ol )
      {
          ...
      }
}

Затем, вне зависимости, в отображении NHibernate велит использовать поле _orderLines:

<set name="OrderLine" access="field.camelcase-underscore" ... >
...
</set>
9 голосов
/ 15 марта 2009

Шаблон, который я использую:

class Order
{
   private List<OrderLine> lines = new List<OrderLine>();

   IEnumerable<OrderLine> Lines { get { return this.lines; } }

   void AddLine(OrderLine line)
   {
       this.orders.Add(line);
   }
}

Если вы используете NET 3.5, вы получаете все функции поиска, которые вы могли бы использовать для IEnumerable с помощью LINQ, и вы скрываете реализацию своей коллекции.

Проблема с возвратом OrderLine [] заключается в том, что ваша коллекция может быть изменена извне, например:

Order.Lines[0] = new OrderLine().
3 голосов
/ 15 марта 2009

Я представляю коллекции как ReadOnlyCollection и использую методы AddX и RemoveX для поддержки коллекций. Мы только что перешли на 3.5, и вместо этого я собираюсь разоблачить IEnumerable. В большинстве случаев с NHibernate дочерний элемент имеет ссылку на родителя, поэтому предоставление методов Add и Remove позволяет поддерживать эти отношения:

    public void AddPlayer(Player player)
    {
        player.Company = this;
        this._Players.Add(player);
    }

    public void RemovePlayer(Player player)
    {
        player.Company = null;
        this._Players.Remove(player);
    }
1 голос
/ 15 марта 2009

Если я выставляю список, который не должен быть изменен, тогда я использую IEnumerable и yield. Я нахожу это громоздким, пытаясь использовать ReadOnlyCollections в сочетании с NHiberante.

При таком подходе у вас все еще есть поле приватных линий, которое отображается и заполняется через NHibernate; однако публичный доступ к коллекции осуществляется через итераторы. Вы не можете добавлять или удалять из базового списка с помощью этого свойства Lines.

Например:

public IEnumerable<OrderLine> Lines {
    get {
        foreach (OrderLine aline in lines) {
            yield return aline;
        }
    }
}
0 голосов
/ 25 августа 2013

Я провел несколько дней в поисках лучшего подхода для списков только для чтения в NHibernate. Эта дискуссия очень помогла мне сформировать тот, который подходит нашему проекту.

Существует подход, который я начал использовать:

  1. Поля поддержки используются для хранения коллекций
  2. IEnumerable используется для предоставления коллекций, чтобы заставить клиентов использовать методы AddLine () и RemoveLine ().
  3. В дополнение к IEnumerable используется тип ReadOnlyCollection.

Код:

public class Order
{
    private readonly IList<OrderLine> lines = new List<OrderLine>();

    public virtual IEnumerable<OrderLine> Lines
    {
        get
        {
            return new ReadOnlyCollection<OrderLine>(lines);
        }
    }

    public void AddLine(OrderLine line)
    {
        if (!lines.Contains(line))
        {
            this.lines.Add(line);
            line.Order = this;
        }
    }

    public void RemoveLine(OrderLine line)
    {
        if (lines.Contains(line))
        {
            this.lines.Remove(line);
            line.Order = null;
        }
    }
}

public class OrderLine
{
    public Order Order { get; set; }
}
...