开发者

EF 4.1, POCO: Reference type properties are not updated in case AutoDetectChanges=false

EF 4.1, POCO: I turned off AutoDetectChanges (Configuration.AutoDetectChangesEnabled = false) to speed up data update. Then I run Add or Attach with entity state changed to EntityState.Modified. All this causes references to other objects not being updated in database. However all scalar properties are updated successfully.

Profiler shown EF generates SQL update operation for every scalar property, but not for reference type, though I really changed its value in my code. This issue reproduced for every type of ent开发者_如何学Pythonity in my model.

Add operation or Attach with EntityState.Added both work fine. If I turn AutoDetectChanges back on, everything works fine as expected for updated records too.

Help me please to figure out what's wrong. I can not find any good comprehensive documentation on EF's Detect Changes.

UPDATE

I was asked to put some example of code to reproduce the issue. Domain:

public class Client
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Address Address { get; set; }
}

public class Address
{
    public int Id { get; set; }
    public virtual string City { get; set; }
}

DataContext:

public class DataContext : DbContext
{

    public DbSet<Client> Clients { get; set; }
    public DbSet<Address> Address { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Client>().HasOptional(c => c.Address);
    }
}

Add one record to Clint table and one to Address. Point Client to the Address. Then run the following code:

using (var cntx = new DataContext())
{
    cntx.Configuration.AutoDetectChangesEnabled = false; // Reason of problem
    var client = cntx.Clients.First();
    client.Name = "Anna"; // This property will be updated
    client.Address = null;  // This property will not be updated
    cntx.Clients.Attach(client);
    cntx.Entry(client).State = EntityState.Modified;
    cntx.SaveChanges();
}

This code does generates SQL script like this:

update [dbo].[Clients] set [Name] = 'Anna'
where ([Id] = 1)

Set AutoDetectChangesEnabled to true and run the code again, this time everything alright:

update [dbo].[Clients]
set [Name] = 'Anna', [Address_Id] = null
where (([Id] = 1) and [Address_Id]=1)

Note it does not matter if you change Address's value from specific value to null, or back to specific value, or one concrete value to other concrete value, any change is not tracked while AutoDetectChanges=false. Seems like EF bug.


See Change Tracking on MSDN


Well, I found out the way to set Reference property values that works even with AutoDetectChangesEnabled=false:

cntx.Entry(client).Reference(c => c.Address).CurrentValue = null;

However I definitely do not like it. 1) Code looks ugly; 2) You have to have access to context to make it work, which is not my case, I'd like this property being set outside of repository which only has access to DbContext. Is any other simpler way to let EF know the property value is changed?

Updated: Ok, I found simpler workaround: just run cntx.ChangeTracker.DetectChanges() before running cntx.SaveChanges(). It helps EF generate correct SQL update script

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜