Entity Framework POCO - как предотвратить ошибку, если поле обновляется дважды? - PullRequest
3 голосов
/ 08 ноября 2011

Я начинаю работать с Entity Framework, используя POCO в конфигурации первой модели.У меня есть немного нестандартная модель - сгенерированная путем настройки файла .tt, чтобы он отвечал на пользовательские свойства в .edmx, позволяя мне запускать событие NotifyPropertyChanged для регистрации обновлений определенных свойств - что приводит к классу, который фактически выглядит немного похожимthis:

public partial class MyClass: INotifyPropertyChanged
{
    /// <summary>
    /// Catches events to be added to the UserLog
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Notifies any event listeners attached to the PropertyChanged event that a loggable field
    /// update has occurred.
    /// </summary>
    /// <param name="eventType">The type of the field.</param>
    /// <param name="message">The message to record in the logs</param>
    private void NotifyFieldUpdate(string eventType, string message)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new LogEventArgs(eventType, message));
        }
    }


  private  string _myField;
  public virtual string MyField
    {
      get
      {
        return _myField;
      }
      set 
      {
        if ( _myField != value )
          {
        _myField = value;
        NotifyFieldUpdate( "FIELDCHANGE", String.Format("MyField changed to {0}", value) );
          }
        }
      }
  }

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

Проблема, с которой я сталкиваюсь, заключается в том, что, если он обновляется дважды, он падаетover:

  public void TestBehaviour(ObjectContext currentContext)
  {
    MyClass testMe = FetchFromObjectContext(currentContext);
    testMe.MyField = "Hello";
    currentContext.SaveChanges();
    testMe.MyField = "Goodbye";
  }

В тот момент, когда я вызываю второй из этих методов, я сталкиваюсь со следующей ошибкой:

EntityMemberChanged или EntityComplexMemberChanged вызывается без первого вызова EntityMemberChanging или EntityComplexMemberChanging для того жеизменить трекер с тем же именем свойства.Информацию о том, как правильно сообщать об изменениях, см. В документации Entity Framework.

Я пытался использовать currentContext.DetectChanges() и currentContext.Refresh( ... ), но это действительно обезьяна, поскольку я не знаю, что именно происходит,

Мой первый вопрос: что является причиной проблемы и что я должен делать с ObjectContext, чтобы избежать ошибок такого типа?Мне кажется вполне вероятным, что поля могут время от времени обновляться, и я бы не хотел, чтобы моя система упала, если это произошло дважды.

Мой второй, возможно, более глубокий вопрос: я приближаюсь?все это неправильно, используя интерфейс INotifyPropertyChanged, когда кажется, что класс уже запускает эти EntityMemberChanged события?Я предполагаю, что это потому, что ObjectContext создает прокси-сервер. Значит ли это, что в некоторых случаях эти методы могут быть недоступны, если у меня нет собственных уведомлений?

Ответы [ 4 ]

1 голос
/ 09 июля 2013

Если вы не можете отключить прокси и иметь виртуальный столбец Timestamp, не вызывайте RaisePropertyChanged для этого свойства. http://softwaremechanik.wordpress.com/2013/07/09/ef-poco-invalidoperationexception-entitymemberchanged-in-savechanges-timestamp-column/

1 голос
/ 19 ноября 2011

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

0 голосов
/ 16 ноября 2011

Оказывается, основная причина проблемы, как я и подозревал, была связана с созданием прокси моим ObjectContext.

Чтобы устранить ошибку и - в моем случае - соответственно решитьпроблема, мне просто нужно было добавить

currentContext.ContextOptions.ProxyCreationEnabled = false;

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

Полезный ресурс: MSDN по работе с объектами POCO

0 голосов
/ 15 ноября 2011

Я полагаю, это потому, что вы передаете ObjectContext потоку пользовательского интерфейса, и он не является потокобезопасным.

Я думаю, что вы правы, что вам нужно переосмыслить, как вы справляетесь с этим (в основном, с доступом к данным в событиях PropertyChanged).

См. Раздел «Замечания» здесь: http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx

...