数据库上下文 - 多种用法
本文关键字:用法 上下文 数据库 | 更新日期: 2023-09-27 18:34:44
所以我刚才偶然发现了一件奇怪的事情。我有一个测试,它将workingsite
的until
日期更改为昨天,如下所示:
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);
}
在此测试中,我的断言失败,并且对象workingSiteFromDb
的until
没有更改,但在我的代码中,我确实更改了它并将更改保存到数据库中。注意:我的数据库确实更新了!我在数据库中进行了检查,日期更改正确。
现在我不知道发生了什么,所以我在第一次savechanges
后立即停止了using
,并在我打电话之前再次打开workingSiteFromDb
。
如果我这样做,它就会起作用。
请注意,我在 EndWorkingSitePeriod
方法中使用了另一个using
。
为什么我的数据库确实更新了,但对象仅在我使用第二个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
设置为DateTime.Now.AddDays(-1)
,您在某处获取workingSiteToEnd
并将其添加到上下文中,在示例的第一行中创建。然后,您将保存更改(现在workingSiteToEnd
保存在数据库和上下文中(。
然后,您将EndWorkingSitePeriod
方法中创建第二个上下文。使用该上下文,您将获得新的workingSiteFromDb
实例(它与上面的workingSiteToEnd
无关(。您正在修改它,并保存更改。
现在,您正在尝试测试所做的更改,但原始workingSiteToEnd
仍然存在于上下文中。这意味着,当您尝试再次从数据库加载它时,上下文将在具体化过程中查找其本地缓存中具有相同键的实体,将找到它,并将返回现有实体,该实体是原始的,未更改的workingSiteToEnd
(您可以比较引用,它们将是相等的(。
当您在第一次SaveChanges
块后立即关闭using
块,然后创建新块时,您正在创建新的上下文,这将加载workingSiteFromDb
的新实例,并且测试将通过。
不要嵌套使用同一 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);
}
}