What is the best practice for readonly lists in NHibernate
我正在处理的域模型具有根聚合和子实体。类似下面的代码:
1 2 3 4 5 6 7 8 | class Order { IList<OrderLine> Lines {get;set;} } class OrderLine { } |
现在我要我的订单控制线路。就像这样:
1 2 3 4 5 6 | class Order { OrderLine[] Lines {get;} void AddLine(OrderLine line); } |
此时,我们使用以下模式:
1 2 3 4 5 6 7 8 9 10 | class Order { private IList<OrderLine> lines = new List<OrderLine>(); OrderLine[] Lines {get {return this.lines;}} void AddLine(OrderLine line) { this.orders.Add(line); { } |
nHibernate直接映射到Lines字段。
现在有问题…
- 你在这种情况下做什么练习?
- 是否有人使用以下方法:公共IEnumerable GetLines()。
- 您使用什么作为属性的返回类型?可以是ReadOnlyCollection或IEnumerable;
- 请问这不是最好的地方吗?请建议。
更新:似乎IEnumerable获胜,但解决方案仍然不完美…
我是这样做的:
1 2 3 4 5 6 7 8 9 10 11 12 13 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"字段:
1 2 3 | <set name="OrderLine" access="field.camelcase-underscore" ... > ... </set> |
我使用的模式是:
1 2 3 4 5 6 7 8 9 10 11 | 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[]的问题是可以从外部修改集合,例如:
1 | Order.Lines[0] = new OrderLine(). |
我将集合公开为readOnlyCollection,并使用addx和removex方法来维护集合。我们刚切换到3.5,我想改为公开IEnumerable。在大多数情况下,使用NHiberinate时,孩子会引用父母,因此暴露添加和删除方法可以让您保持这种关系:
1 2 3 4 5 6 7 8 9 10 11 | public void AddPlayer(Player player) { player.Company = this; this._Players.Add(player); } public void RemovePlayer(Player player) { player.Company = null; this._Players.Remove(player); } |
如果我要公开一个不应该修改的列表,那么我将使用IEnumerable和yield。我觉得把读出器集合与nhibrante结合使用很麻烦。
使用这种方法,您仍然可以使用private lines字段,该字段通过nhibernate进行映射和填充;但是,对集合的公共访问是通过迭代器执行的。不能使用此行属性添加到基础列表或从基础列表中删除。
例如:
1 2 3 4 5 6 7 | public IEnumerable<OrderLine> Lines { get { foreach (OrderLine aline in lines) { yield return aline; } } } |
我花了几天时间寻找一种在nhibernate中查找只读列表的最佳方法。这个讨论帮助我形成了一个适合我们项目的讨论。
我开始使用一种方法:
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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; } } |