Ядро ef.net, свойства вместо полей

Итак, мы портируем старое wpf-приложение в.net core wpf. В рамках этих усилий мы также перемещаем уровень данных в EF.net core,

  1. Поскольку мы используем Prism MVVM, в контексте службы DI мы сохраняем контекст данных в реальном времени, который отслеживает объекты, которые отображаются и редактируются пользователем через интерфейс wpf и через службу.
  2. Чтобы реализовать функцию отмены, мы отслеживаем объекты, используя entity.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotificationsWithOriginalValues);

При редактировании объект обновляется, при перезагрузке () он возвращается к отслеживаемым исходным значениям. Объектно, операции в порядке, однако, сторона wpf не работает нормально. Кажется, ядро ​​ef.net - очень плохо приспособленный гражданин приложения wpf, считая его единственным бенефициаром механизма INotifyPropertyChanged. Что, конечно, не совсем верно для WPF.

  1. EF.net, похоже, не использует свойства при загрузке, перезагрузке и т. Д. Он работает непосредственно с базовыми полями. Как следствие, NotifyPropertyChanged никогда не срабатывает, поэтому сетка никогда не обновляется новыми данными, скажем, dbContext.Entry(c).Reload();, Итак, вопрос № 1, есть ли способ заставить ef.net работать со свойствами, а не с полями?
  2. Реализация ef.net INotifyPropertyChanged кажется ошибочным. Если вы вызываете событие PropoertyChanged для свойства, фактически не изменяя его, оно помечает сущность как Modified, хотя он может легко сравнить исходное и текущее значение. Это запрещает нам вручную поднимать события измененных свойств для управления рендерингом WPF. Не уверен, как решить это, или если это даже решаемо, потому что это относится только к этой стратегии отслеживания. Я открыт для любых предложений о том, как я могу уведомлять элементы WPF, не взламывая ef.net.
  3. Определение состояния объекта является довольно запутанной операцией, включающей dbContext.Entry(entry).State который существует вне каких-либо привязок WPF внутри DataContext иерархия. Это делает привязку к состоянию практически невозможной (например, изменить фон грязных записей или показать кнопку "Сохранить" и т. Д.). Мы "решили" это, унаследовав все наши классы сущностей от NotifySetterObject базовый класс, который обрабатывает INotify* реализация, а также держит [NotMapped] bool IsDirty флаг. Излишне говорить, что мне это очень не нравится, так как два несвязанных флага состояния звучат как несчастный случай, ожидающий случившегося. Мне интересно, сталкивались ли вы с подобной проблемой и разработали ли вы более разумное решение.

EF.net, похоже, претерпел критическое преобразование изменений из фреймворка ef.net с точки зрения того, что он хорошо подходит только для сценариев с отсоединенными контекстами (например, asp.net). Мы тратим наше время здесь, пытаясь надеть эту обувь на wpf? Должны ли мы сосредоточиться на другом ИЛИ движке, более подходящем для живых контекстов?

1 ответ

Решение

Прежде чем пытаться ответить на ваши вопросы, позвольте мне указать на некоторые вещи:

  1. Вы используете EF Core 3.0, который в настоящее время находится в режиме предварительного просмотра (бета), поэтому многие вещи могут работать не так, как ожидалось.

  2. Если по ef.net Вы имеете в виду EF6, то есть старый проект, который вы переносили, использовал EF6, нет необходимости переходить на EF Core - EF6 также получает поддержку.Net Core - предварительная версия доступна здесь.

Теперь относительно ваших конкретных вопросов:

  1. EF Core может использовать свойства, поле или оба. Это настраивается через свободный API на уровне контекста, объекта и свойства. Просто изменилось EF Core 3.0 по умолчанию - вы можете видеть, что в Breaking Changes - Поля поддержки используются по умолчанию. Ссылка также показывает, как получить желаемое поведение с помощью

    .UsePropertyAccessMode(PropertyAccessMode.FieldDuringConstruction)
    

на модели (все сущности), строителя сущности (все свойства сущности) или свойства (свойство конкретной сущности).

  1. Поведение объясняется в документации ChangeTrackingStrategy:

Исходные значения записываются, когда объект поднимает PropertyChanging, Свойства помечаются как измененные, когда объект поднимает PropertyChanged мероприятие.

Так оно и есть, поэтому с этим ничего не поделаешь. Но решение № 1 устраняет необходимость ручного повышения PropertyChanged событие, и двусторонняя привязка, кажется, работает безупречно.

  1. Я не совсем уверен, что именно ты здесь. Но начиная с версии 2.1 EF Core предоставляет 2 события изменения состояния на ChangeTracker - Tracked а также StateChanged, который (особенно второй) может быть использован для предоставления уведомлений об изменении состояния. Но фактический механизм для этого остается за вами. Например, вы можете использовать функцию внедрения службы конструктора сущностей EF Core 2.1+ для внедрения DbContext в сущность, которая в свою очередь может подписаться на StateChanged событие и поднять PropertyChanged для своего собственного не нанесенного на карту State собственность и т. д.
Другие вопросы по тегам