Nhibernate - 初始化列表 - 最佳实践?

时间:2009-06-16 13:44:21

标签: nhibernate list

我只是想知道一些CodeWarning(ConstructorsShouldNotCallBaseClassVirtualMethods),以及是否有更好的方法来做到这一点。我有一个简单的日志收集器类,我使用NHibernate来检索一些对象。

有些时候我自己创建对象(当然)并将它们添加到NHibernate中以保持持久性。确保列表永远不会为NULL的最佳方法是什么。

目前我正在这样做,但似乎并不“完美”。关于这个话题的任何想法?

public class LogRun
{
    public virtual int Id { get; private set; }
    public virtual DateTime StartTime { get; set; }
    public virtual DateTime EndTime { get; set; }
    public virtual IList<Log> LogMessages { get; set; }
    public virtual int LogMessageCount { get { return LogMessages.Count; } }

    public LogRun()
    {
        LogMessages = new List<Log>();
    }


}

2 个答案:

答案 0 :(得分:8)

LogMessages是一个持久的东西吗?如果是这样,最好不要公开公共设置者。如果您从数据库中检索出来然后用新的IList替换该IList,那么NHibernate会变得奇怪:

var myLog = session.Get<LogRun>(1);
Assert.True(myLog.LogMessages.Count > 0);
myLog.LogMessages = new List<Log>();

如果你注意到,NHibernate返回一个代理对象并用通用列表替换它会导致它在你尝试保存时变得不稳定。

作为一项规则,我更喜欢拥有一个我初始化的私有字段,然后只向客户端公开一个getter:

public class LogRun
{
    private IList<Log> logMessages = new List<Log>();

    public virtual int Id { get; private set; } 
    public virtual DateTime StartTime { get; set; } 
    public virtual DateTime EndTime { get; set; }
    public virtual IList<Log> LogMessages { get { return logMessages; } } 
    public virtual int LogMessageCount { get { return LogMessages.Count; } }

    public void AddLogMessage(Log log)
    {
        logMessages.Add(log);
    }
}

实际上,我更进了一步,客户端获得了IEnumerable&lt;&gt;我为add添加了一个辅助函数。

我的诽谤看起来像

public class LogRun
{
    private IList<Log> logMessages = new List<Log>();

    public virtual int Id { get; private set; } 
    public virtual DateTime StartTime { get; set; } 
    public virtual DateTime EndTime { get; set; }
    public virtual IEnumerable<Log> LogMessages { get { return logMessages; } } 
    public virtual int LogMessageCount { get { return LogMessages.Count(); } }

    public void AddLogMessage(Log log)
    {
        logMessages.Add(log);
    }
}

答案 1 :(得分:1)

我做同样的事情,但我也想知道性能影响有多大,因为NHibernate也会创建一个新的List&lt;&gt;对于每个默认构造函数调用..

我认为我们很幸运,而且它会奏效。考虑NHibernate创建一个延迟加载的LogRun列表(这就是我们将所有内容标记为虚拟的原因):

  1. NHibernate将反映LogRun并创建派生类
  2. NHibernate将创建一个LogRun派生类的代理列表
  3. -
  4. 当您加载该代理时,它将实例化其中一些派生类,但是,首先调用基础构造函数 - 创建新列表&lt;&gt; - 然后调用派生的构造函数,改为创建代理列表。
  5. 实际上,我们创建了一个永远不会使用的列表。

    考虑其他选择:

    • 使构造函数受到保护,以便没有人会调用它,并做出替代。例如,静态LogR​​un.GetNew();方法
    • 允许对IList&lt;&gt;进行公开设置访问并在创建新对象时自己创建它。

    老实说,我认为两者都非常混乱,因为我(非常)确定在每个构造函数调用上创建一个新的空列表的性能开销是有限的,这就是我个人迄今为止所坚持的。好吧,至少直到我的探查者告诉我:P