Entity Framework: отмена изменения свойства, если нет изменения в значении - PullRequest
5 голосов
/ 21 января 2009

При установке свойства для объекта сущности оно сохраняет значение в базе данных, даже если значение точно такое же, как и раньше. Есть ли способ предотвратить это?

Пример:

Если я загружаю объект Movie, и в качестве «Заголовка» используется «A», если я снова устанавливаю «Заголовок» в «Заголовок» и SaveChanges (), я надеялся, что не увижу выражение UPDATE в SqlProfiler, но это так. Есть ли способ остановить это?

Ответы [ 4 ]

5 голосов
/ 21 января 2009

Да, вы можете изменить это. Однако в текущей версии Entity Framework это не тривиально. В будущем станет легче.

Причина, по которой вы видите это поведение, заключается в генерации кода по умолчанию для модели сущностей. Вот типичный пример:

public global::System.Guid Id
{
    get
    {
        return this._Id;
    }
    set
    {
        // always!
        this.OnIdChanging(value);
        this.ReportPropertyChanging("Id");
        this._Id = global::System.Data.Objects.DataClasses
                               .StructuralObject.SetValidValue(value);
        this.ReportPropertyChanged("Id");
        this.OnIdChanged();
    }
}
private global::System.Guid _Id;
partial void OnIdChanging(global::System.Guid value);
partial void OnIdChanged();

Эта генерация кода по умолчанию является разумной, потому что Entity Framework не знает семантики того, как вы собираетесь использовать значения. Типы в свойстве могут или не могут быть сопоставимы, и даже если они есть, каркас не может знать, как вы собираетесь использовать ссылочное равенство и равенство значений во всех случаях. Для определенных типов значений, таких как десятичное, это довольно ясно, но в общем смысле это не очевидно.

Вы, с другой стороны, знаете свой код и можете его настроить. Проблема в том, что это сгенерированный код, поэтому вы не можете просто войти и отредактировать его. Вам нужно либо взять на себя генерацию кода, либо сделать его ненужным. Итак, давайте посмотрим на три варианта.

Взять на себя генерацию кода

Существенным подходом здесь является создание шаблона T4, который выполняет код и который является генерацией кода по умолчанию из Entity Framework. Вот один пример. Одним из преимуществ этого подхода является то, что Entity Framework перейдет к генерации T4 в следующей версии , поэтому ваш шаблон, вероятно, будет хорошо работать в будущих версиях.

Устранить генерацию кода

Второй подход заключается в том, чтобы полностью исключить когенерацию, а сделать вашу поддержку отслеживания изменений вручную, через IPOCO . Вместо того чтобы изменять способ генерации кода, при таком подходе вы вообще не производите генерацию кода, а вместо этого предоставляете поддержку отслеживания изменений в Entity Framework путем реализации нескольких интерфейсов. См. Связанный пост для более подробной информации.

Подождите

Другой вариант - жить с Entity Framework, как он есть на данный момент, и ждать следующего релиза, чтобы получить желаемое поведение. В следующей версии Entity Framework по умолчанию будет использоваться T4 , поэтому настройка генерации кода будет очень простой.

4 голосов
/ 21 января 2009

Согласно MSDN :

Состояние объекта изменено с Не изменяется на Изменено всякий раз, когда свойство setter называется. Это происходит даже когда установленное значение является такой же, как текущее значение. После Метод AcceptAllChanges вызывается, состояние возвращается в Без изменений. От по умолчанию вызывается AcceptAllChanges во время операции SaveChanges.

Похоже, вы захотите проверить значение свойств объектов Entity перед обновлением, чтобы предотвратить оператор UPDATE.

0 голосов
/ 11 февраля 2015

Одна вещь, которую вы можете сделать, это просто обернуть свойство, используя частичный файл класса, а затем использовать ваше свойство вместо первого:

public sealed partial class MyEFType {
   public string MyWrappedProperty {
      get {
         return MyProperty;
      }
      set {
         if (value == MyProperty)
            return;
         MyProperty = value;
      }
   }
}

Было бы не очень практично делать это для каждого свойства, но если вам нужно обнаружить, что конкретное свойство действительно изменилось, а не просто записано, что-то подобное может сработать .

0 голосов
/ 21 января 2009

На общем уровне, если ваши сущности реализуют INotifyPropertyChanged, вы не хотите запускать событие PropertyChanged, если значение совпадает. Так что каждое свойство выглядит так: -

    public decimal Value
    {
        get
        {
            return _value;
        }
        set
        {
            if (_value != value)
            {
                _value = value;
                if (_propertyChanged != null) _propertyChanged(this, new PropertyChangedEventArgs("Value"));
            }
        }

    }

Надеюсь, что это относится к Entity Framework.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...