2012-01-16 14 views
7

Creo que me falta algo conceptual con respecto a NHibernate. Tengo un objeto Instrument que se asigna a una tabla instruments en mi base de datos. También tengo un objeto BrokerInstrument que se asigna a mi tabla brokerInstruments en mi base de datos. brokerInstrumnets es una tabla secundaria de instruments. Mis clases se parecen:Ciclo de vida del objeto en NHibernate

public class Instrument : Entity 
{ 
    public virtual string Name { get; set; } 
    public virtual string Symbol {get; set;} 
    public virtual ISet<BrokerInstrument> BrokerInstruments { get; set; } 
    public virtual bool IsActive { get; set; }   
} 

public class BrokerInstrument : Entity 
{ 
    public virtual Broker Broker { get; set; } 
    public virtual Instrument Instrument { get; set; } 
    public virtual decimal MinIncrement { get; set; } 
} 

En mi prueba de unidad, si puedo recuperar un Instrument de la base de datos y luego eliminarlo con ISession.Delete, se elimina de la base de datos junto con los niños (tengo cascada, todo encendido en mi archivo de mapeo). Sin embargo, el Instrument aún existe en la memoria. Por ejemplo:

[Test] 
    public void CascadeTest() 
    { 
     int instrumentId = 1; 
     IInstrumentRepo instruments = DAL.RepoFactory.CreateInstrumentRepo(_session); 
     Instrument i = instruments.GetById<Instrument>(instrumentId); // retrieve an instrument from the db 
     foreach (BrokerInstrument bi in i.BrokerInstruments) 
     { 
      Debug.Print(bi.MinIncrement.ToString()); // make sure we can see the children 
     } 

     instruments.Delete<Instrument>(i); // physically delete the instrument row, and children from the db 

     IBrokerInstrumentRepo brokerInstruments = DAL.RepoFactory.CreateBrokerInstrumentRepo(_session); 
     BrokerInstrument deletedBrokerInstrument = brokerInstruments.GetById<BrokerInstrument>(1); // try and retrieve a deleted child 
     Assert.That(instruments.Count<Instrument>(), Is.EqualTo(0)); // pass (a count in the db = 0) 
     Assert.That(brokerInstruments.Count<BrokerInstrument>(), Is.EqualTo(0)); // pass (a count of children in the db = 0) 
     Assert.That(i.BrokerInstruments.Count, Is.EqualTo(0)); // fail because we still have the i object in memory, although it is gone from the db 

    } 

¿Cuál es la mejor práctica con respecto al objeto en la memoria? Ahora estoy en un estado incoherente porque tengo un objeto Instrument en memoria que no existe en la base de datos. Soy un programador novato, por lo que las respuestas detalladas con enlaces son muy apreciadas.

Respuesta

2

Algunas cosas. Su _sesión es en efecto su unidad de trabajo. Todo el trabajo que estás haciendo aquí es borrar el instrumento i. Quizás envuelva ese código en un uso (_session).

Cuando está haciendo sus afirmaciones. Haga una nueva sesión para hacer los controles de recuperación.

En lo que respecta al objeto "i", en primer lugar, no lo denomine yo, ya que solo debería utilizarse para los contadores de bucle. En segundo lugar, en esta afirmación Assert.That(i.BrokerInstruments.Count, Is.EqualTo(0)) el recuento de i.BrokerInstruments no se cambiaría necesariamente a menos que su implementación para IInstrumentRepo.Delete (Instrument someInstrument) establezca explícitamente algunos instrumentos en null.

Espero que esto ayude un poco.

0

Si elimina Instrument por instruments.Delete<Instrument>(i); Nhibernate eliminará el objeto y sus colecciones de la memoria caché de primer nivel y lo separarán y los objetos permanecerán en la memoria como separados, si necesita eliminar objetos de la memoria que necesita después de eliminarlos comprobar si la sesión contiene objeto eliminado y retirar manualmente de la memoria, se puede proceder de esta manera:

if (!Session.Contains(instruments)) 
{ 
    instruments= null; 
} 

aunque recuerda .NET utiliza un recolector de basura, por lo que establecer a cero no significa que se ha ido de la memoria inmediata, le corresponde al recolector de basura quitarlo cuando llegue a él.

Cuestiones relacionadas