Eine Transaktion mit mehreren Datenbankkontexten
Ich verwende Transaktionen in meinen Unit-Tests, um Änderungen zurückzusetzen. Der Komponententest verwendet einen Datenbankkontext, und der Dienst, den ich teste, verwendet seinen eigenen. Beide sind in eine Transaktion eingeschlossen, und ein Datenbankkontext befindet sich im Block des anderen. Die Sache ist, wenn der innere dbcontext seine Änderungen speichert, ist es nicht sichtbar für den äußeren dbcontext (und ich glaube nicht, dass es daran liegt, dass der andere dbcontext das Objekt möglicherweise bereits geladen hat). Hier ist das Beispiel:
[TestMethod]
public void EditDepartmentTest()
{
using (TransactionScope transaction = new TransactionScope())
{
using (MyDbContext db = new MyDbContext())
{
//Arrange
int departmentId = (from d in db.Departments
where d.Name == "Dep1"
select d.Id).Single();
string newName = "newName",
newCode = "newCode";
//Act
IDepartmentService service = new DepartmentService();
service.EditDepartment(departmentId, newName, newCode);
//Assert
Department department = db.Departments.Find(departmentId);
Assert.AreEqual(newName, department.Name,"Unexpected department name!");
//Exception is thrown because department.Name is "Dep1" instead of "newName"
Assert.AreEqual(newCode, department.Code, "Unexpected department code!");
}
}
}
Der Service:
public class DepartmentService : IDepartmentService
{
public void EditDepartment(int DepartmentId, string Name, string Code)
{
using (MyDbContext db = new MyDbContext ())
{
Department department = db.Departments.Find(DepartmentId);
department.Name = Name;
department.Code = Code;
db.SaveChanges();
}
}
}
Wenn ich jedoch den äußeren dbcontext schließe, bevor ich den Dienst aufrufe, und einen neuen dbcontext für die Zusicherung öffne, funktioniert alles einwandfrei:
[TestMethod]
public void EditDepartmentTest()
{
using (TransactionScope transaction = new TransactionScope())
{
int departmentId=0;
string newName = "newName",
newCode = "newCode";
using (MyDbContext db = new MyDbContext())
{
//Arrange
departmentId = (from d in db.Departments
where d.Name == "Dep1"
select d.Id).Single();
}
//Act
IDepartmentService service = new DepartmentService();
service.EditDepartment(departmentId, newName, newCode);
using (MyDbContext db = new MyDbContext())
{
//Assert
Department department = db.Departments.Find(departmentId);
Assert.AreEqual(newName, department.Name,"Unexpected department name!");
Assert.AreEqual(newCode, department.Code, "Unexpected department code!");
}
}
}
Im Grunde habe ich eine Lösung für dieses Problem (ich habe beim Schreiben dieser Frage darüber nachgedacht), aber ich frage mich immer noch, warum es nicht möglich ist, auf nicht festgeschriebene Daten in der Transaktion zuzugreifen, wenn die DB-Kontexte verschachtelt sind. Könnte es sein, weil die Verwendung von (dbcontext) wie eine Transaktion selbst ist? In diesem Fall verstehe ich das Problem immer noch nicht, da ich .SaveChanges () im inneren dbcontext aufrufe.