Pregunta Nhibernate - Inicializar listas - ¿Mejores prácticas?


Me preguntaba acerca de algunos CodeWarning (ConstructorsShouldNotCallBaseClassVirtualMethods), y si hay una mejor manera de hacerlo. Tengo una clase de recopilador de registro simple y estoy usando NHibernate para recuperar algunos de los objetos.

Algunas veces creo objetos por mí mismo (por supuesto) y los agrego a NHibernate para la persistencia. ¿Cuál es la mejor manera de asegurarse de que Las listas nunca son NULL.

Actualmente estoy haciendo esto, pero no parece "perfecto". Alguna idea sobre este tema?

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
2018-06-16 13:44


origen


Respuestas:


¿Es LogMessages una cosa persistida? Si es así, es una buena práctica nunca exponer a un colocador público. NHibernate se vuelve extraño si te retiras de la base de datos y luego reemplazas ese IList con uno nuevo:

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

Si nota, NHibernate está devolviendo un objeto proxy y reemplazarlo con una lista genérica hará que no funcione cuando intente guardar de nuevo.

Como regla, prefiero tener un campo privado que inicializo y luego expongo solo un getter al cliente:

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);
    }
}

En realidad, voy un paso más allá, el cliente obtiene un IEnumerable <> y yo agrego una función auxiliar para el complemento.

Mi implementación parecería

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
2018-06-16 14:48



Hago lo mismo, pero también me pregunto qué tan grande es el impacto del rendimiento, ya que NHibernate también creará una nueva Lista <> para cada llamada de constructor predeterminada.

Creo que estamos en suerte, y que funcionará. Considere la posibilidad de que NHibernate cree una lista de LogRun con carga lenta (por eso marcamos todo como virtual de todos modos):

  1. NHibernate reflexionará sobre LogRun y ​​creará una clase derivada
  2. NHibernate hará una lista proxy de la clase derivada de LogRun
  3. -
  4. Cuando carga ese proxy, creará una instancia de algunas de esas clases derivadas, sin embargo, primero se llama al constructor base (crear la nueva lista <>) y luego se llama al constructor derivado, creando una lista de proxy en su lugar.

Efectivamente, hemos creado una lista que nunca usaremos.

Considere las alternativas sin embargo:

  • Haga que el constructor esté protegido, de modo que nadie lo llame, y haga una alternativa. Por ejemplo, un LogRun.GetNew () estático; método.
  • Permita el acceso público al sistema IList <> y créelo usted mismo cada vez que cree un nuevo objeto.

Honestamente, creo que ambos son muy desordenados, y como estoy (bastante) seguro de que la sobrecarga de rendimiento en la creación de una nueva lista vacía en cada convocatoria de constructores es limitada, eso es lo que personalmente me quedo hasta ahora ... Bueno, al menos hasta que mi perfilador me diga lo contrario: P


1
2018-06-16 13:56