简体   繁体   中英

Db context - multiple usages

so I stumbled upon a weird thing just now. I have a test which changes the until date of a workingsite to yesterday like so:

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);
        }

In this test my assert fails and the until hasn't changed for the object workingSiteFromDb , yet in my code I do change it and save changes to the database. note : my database did update! I checked inside the database and the date is altered correctly.

Now I didn't know what was going on and so I stopped the using right after the first savechanges and opened it again right before I call workingSiteFromDb .

If I do this, it works.

Note that I use another using within the EndWorkingSitePeriod method.

How come my database does update but the object only updates when I use a second using ?

This is the EndWorkingSitePeriod method:

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();
        }
    }

The workingSite.EndPeriod just sets the UntilDate to DateTime.Now.AddDays(-1)

First, you're obtaining workingSiteToEnd somewhere and adding it to context, created in 1st line of your sample. Then, you're saving the changes ( workingSiteToEnd now in the database and in the context).

Then, you're creating the second context in EndWorkingSitePeriod method. Using that context, you're obtaining new workingSiteFromDb instance (it doesn't relate to workingSiteToEnd from above). You're modifying it, and saving changes.

Now, you're trying to test the changes you've made, but original workingSiteToEnd is still present in context. This means, that when you'll try to load it from database again, context, during materialization process, will look up for entity with the same key in its local cache, will find it, and will return existing entity, which is original , unchanged workingSiteToEnd (you can compare references, they'll be equal).

When you're closing using block right after first SaveChanges , and then creating new one, you're creating new context, which will load new instance for workingSiteFromDb , and the test will pass.

Do not nest usings of the same DbContext. Instead, if you need to use the same context in called method, pass it with parameter, eg:

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);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM