tickwave
tickwave

Reputation: 3445

Confuse about tracking in EF (updating entity with child collection)

So I'm new to EF (I'm using EF6) and I have problem understanding the concept, I'm trying to update entity with child collection.

Here's my entity class :

public class TimeSheet
{
    public int TimeSheetID { get; set; }
    public virtual ICollection<TimeSheetDetail> Details { get; set; }
}

public class TimeSheetDetail
{
    public int TimeSheetDetailID { get; set; }
    public int TimeSheetID { get; set; }
    public virtual TimeSheet TimeSheet { get; set; }
}

My update method :

public void Update(TimeSheet obj)
{
    var objFromDB = Get(obj.TimeSheetID);
    var deletedDetails = objFromDB.Details.Except(obj.Details).ToList();

    _dbContext.Entry(obj).State = EntityState.Modified;

    //track if details exist
    foreach (var details in obj.Details)
    {
        _dbContext.Entry(details).State = details.TimeSheetDetailID == 0 ? EntityState.Added : EntityState.Modified;
    }

    //track deleted item
    foreach (var deleted in deletedDetails)
    {
        _dbContext.Entry(deleted).State = EntityState.Deleted;
    }
}

public TimeSheet Get(object id)
{
    //return _timeSheet.Find(id); //Without AsNoTracking I got error
    int x = Convert.ToInt32(id);
    return _timeSheet.AsNoTracking().SingleOrDefault(a => a.TimeSheetID == x);
}

Above code give me Attaching an entity of type 'ClassName' failed because another entity of the same type already has the same primary key value. So my quesstion is :

  1. How do you update child collection with EF? Means that I need to Add new if it doesn't exist in DB, update otherwise, or delete from DB if it is removed in the POST.

  2. If I don't use AsNoTracking(), it will throw Saving or accepting changes failed because more than one entity of type 'ClassName' have the same primary key value. I notice that the error was cause by my DbSet add the data from DB to its Local property if I don't use AsNoTracking() which cause the EF framework to throw the error because it thinks I have a duplicate data. How does this work actually?

  3. As you can see I'm trying to compare objFromDb against obj to check if user remove one of the details so I can remove it from the database. Instead I got bunch of DynamicProxies from the collection result. What is DynamicProxies and how does it work?

  4. Is there any good article or 101 tutorial on EF? So far I've only see a simple one which doesn't help my case and I've looking around and find a mixed answer how to do stuff. To be honest, at this point I wish I would just go with classic ADO.Net instead of EF.

Upvotes: 3

Views: 3033

Answers (1)

JoeJoe87577
JoeJoe87577

Reputation: 522

For a better understanding of the entity framework, think of the DbContext as proxy between your application and the database. The DbContext will cache everything and will use every bit of data from the cached values unless you tell it not to do so.

For 1.: This depends on your environment if your DbContext is not disposed between selecting and updating the entites you can simply just call SaveChanges and your data will be saved. If your DbContext is disposed you can detach the entites from the context, change the data, reattach them and set the EntityState to modified.

I can't give you a 100% sure answer, because I stopped using the entity framework about half a year ago. But I know it is a pain to update complex relations.

For 2.: The command AsNoTracking tells the EF not to track the changes made to the entities inside this query. For example your select 5 TimeSheets from your Database, change some values in the first entity and delete the last one. The DbContext knows that the first entity is changed and the last one is deleted, if you call SaveChanges the DbContext will automatically update the first entity , delete the last one and leave the other ones untouched. Now you try to update an entity by yourself and attach the first entity again to the DbContext.

The DbContext will now have two entites with the same key and this leads to your exception.

For 3.: The DynamicProxies is the object that the entity framework uses to track the changes of these entities.

For 4.: Check this link, also there is a good book about entity framework 6 (Title: "Programming Entity Framework")

Upvotes: 3

Related Questions