Db上下文 - 多种用法

时间:2014-12-19 08:36:54

标签: c# entity-framework

所以我刚才偶然发现了一件奇怪的事情。 我有一个测试会将until的{​​{1}}日期更改为昨天,如此:

workingsite

在此测试中,我的断言失败,using (var db = new ApplicationDbContext()) { var empFromDb = db.Employees.Include(x => x.WorkingSites).First(x => x.Id == _employeeId); empFromDb.WorkingSites.Add(workingSiteToEnd); db.SaveChanges(); //Act ServiceFactory.CreateEmployeeService().EndWorkingSitePeriod(workingSiteToEnd); //Assert var workingSiteFromDb = db.WorkingSites.First(x => x.Id == workingSiteToEnd.Id); Assert.AreEqual(DateTime.Now.AddDays(-1).Date, workingSiteFromDb.WorksUntil.Date); } 没有为对象until更改,但在我的代码中,我确实更改了它并将更改保存到数据库中。 注意:我的数据库更新!我检查了数据库内部并正确更改了日期。

现在我还不知道发生了什么,所以我在第一个workingSiteFromDb之后立即停止using,并在我致电savechanges之前再次打开它。

如果我这样做,它就有效。

请注意,我在workingSiteFromDb方法中使用了另一个using

为什么我的数据库会更新,但只有当我使用第二个EndWorkingSitePeriod

时,对象才会更新

这是using方法:

EndWorkingSitePeriod

public void EndWorkingSitePeriod(int workingSiteId) { using (var db = new ApplicationDbContext()) { var workingSiteFromDb = db.WorkingSites.Include(x => x.Employee).First(x => x.Id == workingSiteId); workingSiteFromDb.EndPeriod(); db.SaveChanges(); } } 只是将workingSite.EndPeriod设置为UntilDate

2 个答案:

答案 0 :(得分:2)

首先,您在某处获得workingSiteToEnd并将其添加到您在样本第一行中创建的上下文中。然后,您将保存更改(workingSiteToEnd现在在数据库中在上下文中。)

然后,您在EndWorkingSitePeriod方法中创建第二个上下文。使用该上下文,您即可获得 workingSiteFromDb实例(它与上面的workingSiteToEnd无关)。您正在修改它并保存更改。

现在,您正在尝试测试您所做的更改,但原始 workingSiteToEnd仍然存在于上下文中。这意味着,当您再次尝试从数据库加载它时,在实现过程中,上下文将在其本地缓存中查找具有相同密钥的实体,将找到它,并将返回现有实体,即原始,未更改workingSiteToEnd(您可以比较引用,它们相等)。

如果您在第一次using之后立即关闭SaveChanges阻止,然后再创建新的,则会创建上下文,这将加载workingSiteFromDb的新实例,测试将通过。

答案 1 :(得分:0)

不要嵌套相同DbContext的使用。相反,如果您需要在被调用的方法中使用相同的上下文,请使用参数传递它,例如:

using (var db = new ApplicationDbContext())
{
   var empFromDb = db.Employees.Include(x => x.WorkingSites).First(x => x.Id == _employeeId);
   empFromDb.WorkingSites.Add(workingSiteToEnd);
   db.SaveChanges();

   //Act
   ServiceFactory.CreateEmployeeService().EndWorkingSitePeriod(workingSiteToEnd, db);

   //Assert
   var workingSiteFromDb = db.WorkingSites.First(x => x.Id == workingSiteToEnd.Id);

   Assert.AreEqual(DateTime.Now.AddDays(-1).Date, workingSiteFromDb.WorksUntil.Date);
}

private void EndWorkingSitePeriod(int workingSiteId, ApplicationDbContext db)
{
    var workingSiteFromDb = db.WorkingSites.Include(x => x.Employee).First(x => x.Id == workingSiteId);
    workingSiteFromDb.EndPeriod();
    db.SaveChanges();
}

// if you need it public, then use this too
public void EndWorkingSitePeriod(int workingSiteId)
{
    using (var db = new ApplicationDbContext()) 
    {
       EndWorkingSitePeriod(workingSiteId, db);
    }
}