Nhibernate - Initialize Lists - Best Practice?

I'm just curious to learn about CodeWarning (ConstructorsShouldNotCallBaseClassVirtualMethods), and if there is a better way to do this. I have a simple log collector class, and I'm using NHibernate to retrieve some objects.

Several times I create objects myself (of course) and add them to NHibernate for stability. What is the best way to make sure Lists are never NULL.

I am currently doing this, but that does not seem to be "perfect." Any idea on this topic?

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>(); } } 
+6
list nhibernate
source share
2 answers

Is LogMessages Persistent? If so, it's best to never publish a public setter. NHibernate gets weird if you return from the database and then replace this IList with a new one:

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

If you notice that NHibernate returns a proxied object and replaces it with a shared list, it will depend on trying to save it.

As a rule, I prefer to have a private field, which I initialize, and then expose the client only 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); } } 

In fact, I take a step further, the client receives an IEnumerable <> and I add a helper function to add.

My introduction will look like

 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); } } 
+8
source share

I do the same, but I also wonder how great the performance is, since NHibernate will also create a new List <> for each default constructor call ..

I think we were lucky and it will work. Consider NHibernate by creating a lazy LogRun list (so we mark everything as virtual anyway):

  • NHibernate will display over LogRun and create a derived class
  • NHibernate will make a proxy list of class based on LogRun
  • -
  • When you load this proxy, it will create some of these derived classes, however, the base constructor is created first - by creating a new list <> - then the derived constructor is called, creating a proxy list instead.

In fact, we have created a list that we will never use.

Consider the alternatives though:

  • Make the constructor secure so that no one calls it, and make an alternative. For example, static LogRun.GetNew (); Method.
  • Allow public set-access to IList <> and create it yourself each time you create a new object.

Honestly, I think both are very dirty, and since I'm (pretty) sure that the overhead of creating a new empty list on every constructor call is limited, this is something I personally stick too far. Well, at least until my profiler tells me otherwise: P

+1
source share

All Articles