ef.net 核心,属性而不是字段
ef.net core, properties instead of fields
因此,我们正在将一个旧的 wpf 应用程序移植到 .net core wpf 中。作为工作的一部分,我们还将数据层移动到 EF.net core
。
- 由于我们使用 Prism MVVM,在 DI 服务上下文中,我们保留了一个实时数据上下文,它跟踪用户通过 wpf 前端和通过服务显示和编辑的实体。
- 为了实现 "undo" 功能,我们使用以下方法跟踪对象
entity.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotificationsWithOriginalValues);
在编辑时,对象得到更新,在 Reload() 时,它从跟踪的原始值恢复。就对象而言,操作正常,但是,wpf 方面的工作不正常。 ef.net 核心似乎是 wpf 应用程序的一个非常不适应的公民,假设它是 INotifyPropertyChanged 机制的唯一受益者。当然,这对于 WPF 来说一点也不正确。
- EF.net 似乎在加载、重新加载等时不使用属性。它直接作用于底层字段。因此,NotifyPropertyChanged 永远不会触发,因此网格永远不会用新数据刷新,比如说
dbContext.Entry(c).Reload();
。那么问题 #1,有没有办法强制 ef.net 使用属性而不是字段?
INotifyPropertyChanged
的 ef.net 实施似乎有缺陷。如果您在 属性 上调用 PropoertyChanged 事件而不实际更改它,它会将实体标记为 Modified
,即使它可以轻松比较原始值和当前值。这禁止我们手动引发 属性 changed 事件来控制 WPF 渲染。不知道如何解决这个问题,或者它是否可以解决,因为它只适用于这个跟踪策略。我愿意接受任何关于如何通知 WPF 元素而不激怒 ef.net. 的建议
- 确定对象的状态是相当复杂的操作,涉及
dbContext.Entry(entry).State
,它存在于 DataContext
层次结构中的任何 WPF 绑定之外。它几乎不可能绑定状态(例如更改脏条目的背景或显示保存按钮等)。我们 "solved" 它通过从 NotifySetterObject
基础 class 继承我们所有的实体 classes 来处理 INotify*
实现并保留 [NotMapped] bool IsDirty
标志。不用说,我非常不喜欢这个,保留两个未链接的状态标志听起来像是等待发生的事故。我想知道您是否遇到过类似的问题,以及您是否设计了更好、更理智的解决方案。
EF.net 似乎经历了框架 ef.net 的重大变革,仅适用于分离的上下文场景(如 asp.net)。我们是不是在浪费时间试图让这双鞋适合 wpf?我们是否应该专注于更适合实时环境的不同 OR 引擎?
在尝试回答您的问题之前,让我指出一些事情:
您使用的是 EF Core 3.0,目前处于预览(测试版)阶段,因此很多功能可能无法按预期运行。
如果 ef.net
你指的是 EF6,即你正在移植的旧项目使用的是 EF6,那么切换到 EF Core 并不是很有必要 - EF6 也是 getting .Net Core support - a preview version is available here .
现在关于您的具体问题:
EF Core 可以 使用属性、字段或两者。这可以通过 fluent API 在上下文、实体和 属性 级别进行配置。只是 EF Core 3.0 默认值发生了变化——您可以在 Breaking Changes - Backing fields are used by default 中看到这一点。 link 还显示了如何使用
获得所需的行为
.UsePropertyAccessMode(PropertyAccessMode.FieldDuringConstruction)
在模型(所有实体)、实体(所有实体属性)或 属性(特定实体 属性)构建器上。
- ChangeTrackingStrategy 文档中解释了该行为:
Original values are recorded when the entity raises the PropertyChanging
. Properties are marked as modified when the entity raises the PropertyChanged
event.
这是设计使然,因此您无能为力。但解决 #1 消除了手动引发 PropertyChanged
事件的需要,双向绑定似乎完美无缺。
- 我不太确定你到底来这里是为了什么。但是从 v2.1 开始,EF Core 提供了 2 State change events on
ChangeTracker
- Tracked
and StateChanged
, which (especially the second) can be used to provide state change notifications. But the actual mechanism for that is left for you. For instance, you can use EF Core 2.1+ entity constructor service injection 特性来将 DbContext
注入到实体中,实体又可以订阅 StateChanged
事件并为自己未映射的引发 PropertyChanged
State
属性 等
因此,我们正在将一个旧的 wpf 应用程序移植到 .net core wpf 中。作为工作的一部分,我们还将数据层移动到 EF.net core
。
- 由于我们使用 Prism MVVM,在 DI 服务上下文中,我们保留了一个实时数据上下文,它跟踪用户通过 wpf 前端和通过服务显示和编辑的实体。
- 为了实现 "undo" 功能,我们使用以下方法跟踪对象
entity.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotificationsWithOriginalValues);
在编辑时,对象得到更新,在 Reload() 时,它从跟踪的原始值恢复。就对象而言,操作正常,但是,wpf 方面的工作不正常。 ef.net 核心似乎是 wpf 应用程序的一个非常不适应的公民,假设它是 INotifyPropertyChanged 机制的唯一受益者。当然,这对于 WPF 来说一点也不正确。
- EF.net 似乎在加载、重新加载等时不使用属性。它直接作用于底层字段。因此,NotifyPropertyChanged 永远不会触发,因此网格永远不会用新数据刷新,比如说
dbContext.Entry(c).Reload();
。那么问题 #1,有没有办法强制 ef.net 使用属性而不是字段? INotifyPropertyChanged
的 ef.net 实施似乎有缺陷。如果您在 属性 上调用 PropoertyChanged 事件而不实际更改它,它会将实体标记为Modified
,即使它可以轻松比较原始值和当前值。这禁止我们手动引发 属性 changed 事件来控制 WPF 渲染。不知道如何解决这个问题,或者它是否可以解决,因为它只适用于这个跟踪策略。我愿意接受任何关于如何通知 WPF 元素而不激怒 ef.net. 的建议
- 确定对象的状态是相当复杂的操作,涉及
dbContext.Entry(entry).State
,它存在于DataContext
层次结构中的任何 WPF 绑定之外。它几乎不可能绑定状态(例如更改脏条目的背景或显示保存按钮等)。我们 "solved" 它通过从NotifySetterObject
基础 class 继承我们所有的实体 classes 来处理INotify*
实现并保留[NotMapped] bool IsDirty
标志。不用说,我非常不喜欢这个,保留两个未链接的状态标志听起来像是等待发生的事故。我想知道您是否遇到过类似的问题,以及您是否设计了更好、更理智的解决方案。
EF.net 似乎经历了框架 ef.net 的重大变革,仅适用于分离的上下文场景(如 asp.net)。我们是不是在浪费时间试图让这双鞋适合 wpf?我们是否应该专注于更适合实时环境的不同 OR 引擎?
在尝试回答您的问题之前,让我指出一些事情:
您使用的是 EF Core 3.0,目前处于预览(测试版)阶段,因此很多功能可能无法按预期运行。
如果
ef.net
你指的是 EF6,即你正在移植的旧项目使用的是 EF6,那么切换到 EF Core 并不是很有必要 - EF6 也是 getting .Net Core support - a preview version is available here .
现在关于您的具体问题:
EF Core 可以 使用属性、字段或两者。这可以通过 fluent API 在上下文、实体和 属性 级别进行配置。只是 EF Core 3.0 默认值发生了变化——您可以在 Breaking Changes - Backing fields are used by default 中看到这一点。 link 还显示了如何使用
获得所需的行为.UsePropertyAccessMode(PropertyAccessMode.FieldDuringConstruction)
在模型(所有实体)、实体(所有实体属性)或 属性(特定实体 属性)构建器上。
- ChangeTrackingStrategy 文档中解释了该行为:
Original values are recorded when the entity raises the
PropertyChanging
. Properties are marked as modified when the entity raises thePropertyChanged
event.
这是设计使然,因此您无能为力。但解决 #1 消除了手动引发 PropertyChanged
事件的需要,双向绑定似乎完美无缺。
- 我不太确定你到底来这里是为了什么。但是从 v2.1 开始,EF Core 提供了 2 State change events on
ChangeTracker
-Tracked
andStateChanged
, which (especially the second) can be used to provide state change notifications. But the actual mechanism for that is left for you. For instance, you can use EF Core 2.1+ entity constructor service injection 特性来将DbContext
注入到实体中,实体又可以订阅StateChanged
事件并为自己未映射的引发PropertyChanged
State
属性 等