处理类和NHibernate实体中的集合属性

时间:2009-11-25 16:15:51

标签: c# nhibernate oop collections

我想知道在类中公开集合的推荐方法是什么,以及它与使用NHibernate实体时做同样事情的方式有什么不同。

让我解释一下......我的类暴露集合属性时从未遇到过具体问题,如:

IList<SomeObjType> MyProperty { get; set; }

将setter设置为protected或private会让我有时更多地控制我想要处理集合的方式。 我最近遇到了Davy Brion撰写的这篇文章:

http://davybrion.com/blog/2009/10/stop-exposing-collections-already/

Davy,明确建议将集合作为IEnumerables而不是让我们说Lists,以禁止用户选择直接操作这些集合的内容。我可以理解他的观点,但我并不完全相信,通过阅读他的帖子上的评论,我不是唯一的。

当涉及NHibernate实体时,以他提出的方式隐藏集合是特别有意义的,特别是当级联到位时。我希望完全控制会话及其集合中的实体,并且为集合属性公开AddXxx和RemoveXxx对我来说更有意义。

问题是怎么做?

如果我将实体的集合作为IEnumerables我没有办法向它们添加/删除元素而不通过执行ToList()将它们转换为Lists,这会产生一个新的列表,因此没有任何东西可以保留,或者将它们转换为Lists由于代理和延迟加载,这是一种痛苦。

总体思路是不允许检索实体并直接操作其集合(add.remove元素),而只是通过我公开的方法,同时遵守集合持久性的级联。

非常感谢您的建议和想法。

3 个答案:

答案 0 :(得分:8)

怎么样......

private IList<string> _mappedProperty;

public IEnumerable<string> ExposedProperty
{
    get { return _mappedProperty.AsEnumerable<string>(); }
}

public void Add(string value)
{
    // Apply business rules, raise events, queue message, etc.
    _mappedProperty.Add(value);
}

如果您使用NHibernate映射到私有字段,即可以使用此解决方案。 _mappedProperty。您可以在访问和命名策略文档here中阅读有关如何执行此操作的详细信息。

事实上,我更喜欢像这样映射我所有的课程。开发人员更好地决定如何定义类的公共接口,而不是ORM。

答案 1 :(得分:0)

如何将它们公开为ReadOnlyCollection?

IList<SomeObjType> _mappedProperty;

return new ReadOnlyCollection<SomeObjType> ExposedProperty
{
  get
  {
    return new ReadOnlyCollection(_mappedProperty);
  }
}

答案 2 :(得分:0)

我正在使用NHibernate,我通常将集合保留为ISet并使setter受到保护。

ISet<SomeObjType> MyProperty { get; protected set; }

我还为需要它们的集合属性提供AddXxx和RemoveXxx。在大多数情况下,这对我来说非常令人满意。但我要说的是,有些情况下允许客户端代码直接向集合中添加项目。

基本上,我所看到的是,如果我在客户端代码中遵循"Tell, Don't Ask"的原则,而不必担心在我的域对象属性上强制执行严格的访问约束,那么我总是以一个好的设计。