EF 4.1, POCO: свойства ссылочного типа не обновляются в случае, если AutoDetectChanges = false - PullRequest
1 голос
/ 17 августа 2011

EF 4.1, POCO: я выключил AutoDetectChanges ( Configuration.AutoDetectChangesEnabled = false ) для ускорения обновления данных.Затем я запускаю Добавить или Присоединить с измененным состоянием сущности на EntityState.Modified .Все это приводит к тому, что ссылки на другие объекты не обновляются в базе данных.Однако все скалярные свойства успешно обновлены.

Показанный профилировщик EF генерирует операцию обновления SQL для каждого скалярного свойства, но не для ссылочного типа, хотя я действительно изменил его значение в своем коде.Эта проблема воспроизводится для каждого типа объектов в моей модели.

Операция добавления или Присоединение с EntityState.Added , оба работают нормально.Если я включу AutoDetectChanges , все будет работать нормально, как и ожидалось, для обновленных записей.

Помогите, пожалуйста, выяснить, в чем дело.Я не могу найти хорошую исчерпывающую документацию по обнаружению изменений EF.

ОБНОВЛЕНИЕ

Меня попросили привести пример кода для воспроизведения проблемы.Домен:

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

Добавить одну запись в таблицу Клинта и одну в адрес.Укажите клиента на адрес.Затем запустите следующий код:

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

Этот код генерирует скрипт SQL следующим образом:

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

Установите для AutoDetectChangesEnabled значение true и снова запустите код, на этот раз все в порядке:

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

Обратите внимание, что не имеет значения, если вы измените значение адреса с определенного значения на нулевое, или обратно на конкретное значение, или с одного конкретного значения на другое конкретное значение, любое изменение не отслеживается, пока AutoDetectChanges = false.Похоже, ошибка EF.

Ответы [ 2 ]

2 голосов
/ 18 августа 2011

Ну, я нашел способ установить значения свойства Reference, который работает даже при AutoDetectChangesEnabled = false:

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

Однако мне определенно это не нравится.1) код выглядит безобразно;2) Вы должны иметь доступ к контексту, чтобы он работал, что не в моем случае, я хотел бы, чтобы это свойство устанавливалось вне репозитория, который имеет доступ только к DbContext.Есть ли еще какой-нибудь более простой способ сообщить EF об изменении значения свойства?

Обновлено : Хорошо, я нашел более простой обходной путь: просто запустите cntx.ChangeTracker.DetectChanges () перед запуском cntx.SaveChanges().Это помогает EF генерировать корректный скрипт обновления SQL

2 голосов
/ 17 августа 2011
...