私は単体テストでトランザクションを使用して変更をロールバックしています。単体テストはdbcontextを使い、私がテストしているサービスは自分自身を使用します。両方とも1つのトランザクションでラップされ、1つのdbcontextは他のトランザクションのブロック内にあります。問題は、内側のdbcontextが変更を保存するときに、外側のdbcontextには表示されません(他のdbcontextにすでにオブジェクトがロードされている可能性があるためです)。次に例を示します。複数のdbcontextを持つ1つのトランザクション
[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!");
}
}
}
サービス:私はサービスを呼び出す前に、外dbcontextを閉じて、アサートのための新しいdbcontextを開くと
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();
}
}
}
しかし、すべてが正常に動作します:
[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!");
}
}
}
基本的に私はこの問題の解決策を持っていますが(この質問の記述中に考えていますが)、なぜトランザクション内のコミットされていないデータにアクセスできないのか不思議ですdbcontextsがネストされているとき (dbcontext)を使用することはトランザクション自体のようなものでしょうか?もしそうなら、私は内部dbcontextの.SaveChanges()を呼び出しているので、私はまだこの問題を理解していません。
同じ接続文字列であっても、分散トランザクションを持つことができます。それらはクロスサーバ接続よりも軽量になりますが、まだ分散しています。この効果は非決定論的であり、したがって非常に危険である。テストの間、あなたは通常幸運です。 OPは運が良かった。したがって、この回答は受け入れられ、高く評価されていますが、特にこの点では間違っています。 – usr
@usr私は答えを改善するために調べることができるリンクを提供できますか?あなた自身で編集してもよろしいですか? – jnovo
この問題は見つけるのは難しいですが、それに関する「公式の」Microsoftのブログがあり、それを実証しました。私は手元にリンクがありません。 – usr