NHibernate中只读列表的最佳实践是什么?

时间:2009-03-14 13:36:14

标签: .net arrays nhibernate list domain-driven-design

我正在研究的域模型有根聚合和子实体。 类似下面的代码:

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 个答案:

答案 0 :(得分:14)

我这样做:

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>

答案 1 :(得分:9)

我使用的模式是:

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,则可以使用LINQ获得IEnumerable所需的所有搜索功能,并隐藏您的集合实现。

返回OrderLine []的问题是您的集合可以在外部修改,例如:

Order.Lines[0] = new OrderLine().

答案 2 :(得分:3)

我将集合公开为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);
    }

答案 3 :(得分:1)

如果我公开了一个不应修改的列表,那么我使用IEnumerable和yield。我发现尝试将ReadOnlyCollections与NHiberante结合使用会很麻烦。

使用这种方法,您仍然可以通过NHibernate映射和填充私有行字段;但是,通过迭代器执行对集合的公共访问。您无法使用此Lines属性添加或删除基础列表。

例如:

public IEnumerable<OrderLine> Lines {
    get {
        foreach (OrderLine aline in lines) {
            yield return aline;
        }
    }
}

答案 4 :(得分:0)

我花了几天时间为NHibernate中的只读列表寻找最佳方法。 这个讨论帮助我形成了适合我们项目的那个。

我开始使用一种方法:

  1. 支持字段用于存储集合
  2. 的IEnumerable&LT; T&GT;用于公开集合以强制客户端使用AddLine()和RemoveLine()方法。
  3. 除IEnumerable外还使用了ReadOnlyCollection类型。
  4. 代码:

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