Frage

Bei Verwendung von Rhino Commons UnitOfwork (in einer UnitOfworkApplication für ASP-MVC) verwende ich gerne die statische Klasse der Rhino-Repository, um solche Entitäten zu retten:

Repository<Car>.Save(new Car(Id = 1));

Ich finde, dass ich das Entität sofort nach diesem Anruf mit:

Car car = Repository<Car>.Get(1);

Das funktioniert gut. Wenn ich jedoch den Nhibernate Linq -Anbieter auf Rhino Unitofwork wie folgt verwende:

var allCars = (from rep in UnitOfWork.CurrentSession.Linq<Car>()
               select rep).ToList();

Ich bekomme eine leere Liste. Es scheint, dass ich Unitofwork.current.flush () anrufen muss, bevor ich das Auto so herausholen kann. Ich verstehe nicht, warum ich angesichts der Kulissen davon ausgehe, dass beide Abrufmethoden dieselbe Sitzung / Arbeitseinheit abfragen. Bedeutet dies, dass Sie Unitofwork.current.flush () nach jedem Speichern in die Datenbank anrufen sollten? Sollte Nhibernate nicht in der Lage sein, herauszufinden, wann sie sich spülen sollen? Oder verstehe ich etwas falsch?

War es hilfreich?

Lösung

Okay, es scheint, dass zwar ein Aufruf zum Repository den Sitzungs -Cache verwenden kann, das gespeicherte Auto im Cache "sehen" kann:

Car car = Repository<Car>.Get(1); // This works because it uses the same session

Eine LINQ -Abfrage verwendet den Sitzungscache nicht:

var allCars = (from rep in UnitOfWork.CurrentSession.Linq<Car>()               
select rep).ToList(); // Does not work, even if it is in the same code block and even though it uses the same session

Best Practice sind also alle Datenbankänderungen (speichern, aktualisieren, löschen, einfügen) folgen:

UnitOfWork.Session.Flush(), 

oder in a eingewickelt:

With.Transaction(delegate{
   // code here
})

Oder dekorieren Sie Ihre Methode mit [Transaktion] und verwenden Sie ATM. Dadurch wird sichergestellt, dass nachfolgende LINQ-Abfragen aktuelle Daten untersuchen.

Andere Tipps

Wenn Sie repository.save anrufen, informieren Sie die vom Repository gehaltene Sitzung, um dieses Objekt zu verfolgen und die Änderungen an der Datenbank beim nächsten Flush zu synchronisieren. Bis Sie die Sitzung spülen, werden keine Änderungen an der Datenbank vorgenommen. Das Objekt wird jedoch Teil des Sitzungscache und wird daher durch das GET (1) zurückgegeben.

Wenn Sie eine Abfrage ausführen, um eine Sammlung zu füllen, fragt die Sitzung die Datenbank ab, um die Ergebnisse zu erhalten, es sei denn, sie hat diese Ergebnisse bereits zwischengespeichert. Da Sie die Datenbank noch nicht aktualisiert haben, ist das Auto, das Sie der Sitzung hinzugefügt haben, nicht Teil des Ergebnissatzes. (<-möglicherweise falsch) Wenn ich die Dokumentation korrekt lese, sollten sowohl Abfragergebnisse als auch Save () -Entitäten zum Sitzungs-Cache (erste Stufe) hinzugefügt werden. Das bedeutet nicht unbedingt, dass die querystatement.List() Fragen Sie den Cache nach dem Hinzufügen der DB -Ergebnisse ... Es fällt mir schwer, meinen Kopf genau zu wickeln, was los ist.

Abgesehen davon glaube ich, dass Sie die Sitzung auf Autoflush einstellen können, aber ich müsste die Dokumentation überprüfen.

AKTUALISIEREN:

Ich glaube, ich könnte sehen, was hier los ist. Die Standardsitzung FlushMode ist Auto Aber Rhino's UnitOfWork.Start() erstellt eine Sitzung mit einem FlushMode einstellen Commit, Dies bedeutet, dass die Sitzung nicht automatisch fließen wird Flush() oder die Transaktion begehen. Mit einer FlushMode von Auto, Nhibernate wird (manchmal?) Die Sitzung vor der Abfrage spülen, um zu verhindern, dass abgestandene Daten zurückgegeben werden. Wenn ich Recht habe, sieht Ihre DB -Transaktion so aus wie:

SELECT * FROM Car

INSERT INTO Car (...) VALUES (...)

Wenn es automatisch spülen FlushMode = Auto Es spüle "manchmal", obwohl es garantiert Session.Find Wird niemals abgestandene Daten zurückgeben. Da NhiberNate Linq tatsächlich nur eine Kriterienabfrage erstellt, löst dies möglicherweise nicht das Auto -Flush aus (vielleicht wurde dies jetzt behoben ... es ist schwer zu wissen).

Es scheint mir also, dass Sie in Ihrem Fall nach Ihrem Speichern spülen möchten, weil Sie sofort die Ergebnisse Ihres Speicherns abrufen möchten. In einer kleineren Arbeitseinheit, in der Sie nur Einheiten aktualisiert haben, wäre ein einzelnes Commit () in Ordnung. Vielleicht UnitOfWork.CurrentSession.FlushMode = FlushMode.Auto; Würde den Trick machen, aber die Tatsache, dass die Uow -Fabrik explizit den Modus für den Vergehen festlegt, scheint Sie zu ermutigen, wirklich über Ihre Uow -Grenzen nachzudenken.

Dank Stuart Childs habe ich vermute, dass er Recht hat, dass das Problem möglicherweise mit dem Nhibernate Linq -Anbieter liegt. Ich bin mir nicht sicher, was es hinter den Kulissen tut, aber es kann eine andere Sitzung verwenden. Wenn dies der Fall ist, ist es sinnvoll, dass ich das Repository speichern muss, bevor die Linq -Abfrage es "sieht". Zeit, den Quellcode durchzuschauen, aber mir wurde gesagt, dass mein Kopf versucht wird, ihn zu verstehen!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top