2

I am using EF5 with SQL Server 2012 in a web application. I have two classes:

public partial class Topic    {
    public Topic()
    {
        this.SubTopics = new List<SubTopic>();
    }
    public int TopicId { get; set; }
    public string Name { get; set; }
    public int Number { get; set; }
    public virtual ICollection<SubTopic> SubTopics { get; set; }
}

public partial class SubTopic 
{    
    public int SubTopicId { get; set; }
    public int TopicId { get; set; }
    public string Name { get; set; }
    public string Notes { get; set; }
    public virtual byte[] Version { get; set; }
    public virtual Topic Topic { get; set; }
}

In our front-end we make a change to SubTopic Notes and then when a Save button is pressed the Topic object together with its SubTopic Objects are sent back as JSON to the Web API Controller. When we check what is being sent back we see the new data for the Notes. When we check the parameter topic we also see the new Notes data.

public HttpResponseMessage PutTopic(int id, Topic topic)
{
        _uow.Topics.Update(topic); 
        _uow.Commit();
}

However checking with SQL Profiler we cannot see anything happening to change the Sub Topic. When data is retrieved the old SubTopic data is returned and the edit to notes is lost.

For the case of a Web update like this. How does EF determine what has changed and is there some way we can make it check / compare what's there with the new object so that it can detect a change and also update the Subtopic ?

Configuration:

    DbContext.Configuration.ProxyCreationEnabled = false;
    DbContext.Configuration.LazyLoadingEnabled = false;
    DbContext.Configuration.ValidateOnSaveEnabled = false;
    DbContext.Configuration.ValidateOnSaveEnabled = true;
    DbContext.Configuration.AutoDetectChangesEnabled = false;

Update Method:

    public virtual void Update(T entity)
    {
        DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
        if (dbEntityEntry.State == EntityState.Detached)
        {
            DbSet.Attach(entity);
        }  
        dbEntityEntry.State = EntityState.Modified;
    }
Samantha J T Star
  • 28,982
  • 82
  • 233
  • 406

2 Answers2

3

Since ef4.x? EF has a detect changes capability. And it can be made to work for you in an offline object mode.

I assume your UoW handling isn't doing what you would like because of how objects are placed in the context and how the state is managed.

Your main object is attaching an object and then setting it as state changed. But what about all the sub objects? Did they get loaded into the context? Does autodetect changes have something to check? If it is not in the context, then EF cant see the change.

it is important to know when and how EF tracks changes tracking changes in Poco Objects Check the auto detect settings.

this.Configuration.AutoDetectChangesEnabled = false; ////<<<<<<<<< Default true

A pattern that works with EF is:

var mypoco = Context.Set<TPoco>.Find(1);  // find and LOAD your poco or sub object poco
                                          // repeat for graph or use include etc...     
                                          // now in context and changes can be tracked. (see link)
// map json fields to poco entity....
myPoco.propertyXyz = json.ValuesSent; // some mapping approach to move your values, I use this package 
// <package id="ValueInjecter" version="2.3.3" targetFramework="net45" />

// now tell EF things might have changed.
// normally not required by default, But incase your are not using tracking proxies , tell ef check for changes
// Context.Context.ChangeTracker.DetectChanges(); // uncomment when needed

Context.SaveChanged(); // will trigger detect changes in normal scenarios

EF checks those entities loaded for any changes, it has an original state when first attached. So it can now see which properties have changed. It will only update those changed entities and it will Only set the changed properties.

Rap
  • 6,711
  • 2
  • 48
  • 83
phil soady
  • 10,626
  • 4
  • 47
  • 89
1

It seems that the problem is similar to a questions I answered yesterday. Please take a look at my answer

Community
  • 1
  • 1
boindiil
  • 5,687
  • 1
  • 25
  • 30
  • should we be recommending objectContext STE or the DBContext change tracker API ? Your link suggests ObjectContext STE. Or did I mis- understand. furthermore if you set EntityState.Modified in the objectContext and savechanges, all fields whether they are changed or not a written to db. The new DetectChanges is quiet smart in that regard. I also see other reasons to use the new API. Anyway, thats my view: http://msdn.microsoft.com/en-us/data/jj556205 http://msdn.microsoft.com/en-us/library /system.data.entity.infrastructure.dbchangetracker%28v=vs.103%29.aspx – phil soady Aug 06 '13 at 13:24