我正在研究的域模型有根聚合和子实体。 类似下面的代码:
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直接映射到行字段。
现在问题......
更新:似乎IEnumerable获胜,但解决方案仍然不完美...
答案 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中的只读列表寻找最佳方法。 这个讨论帮助我形成了适合我们项目的那个。
我开始使用一种方法:
代码:
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; }
}