I am using transactions in my unit tests to roll back changes. The unit test uses a dbcontext, and the service i'm testing uses his own. Both of them are wrapped in one transaction, and one dbcontext is in the block of the other. The thing is, when the inner dbcontext saves his changes, it's not visible to the outer dbcontext (and i don't think it's because the other dbcontext might already have the object loaded). Here is the example:
[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!");
}
}
}
The 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();
}
}
}
However, if I close the outer dbcontext before calling the service and open a new dbcontext for the assert, everything works fine:
[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!");
}
}
}
So basically i have a solution for this problem (thought of it during the writing of this question) but i still wonder why it isn't possible accessing uncommitted data in the transaction when the dbcontexts are nested.
Could it be becuase using(dbcontext) is like a transaction itself? If so, i still don't understand the issue since i'm calling .SaveChanges() on the inner dbcontext.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…