【问题标题】:ef.net core, properties instead of fieldsef.net 核心,属性而不是字段
【发布时间】:2019-08-01 15:19:19
【问题描述】:

因此,我们正在将旧的 wpf 应用程序移植到 .net core wpf 中。作为努力的一部分,我们还将数据层移动到EF.net core

  1. 由于我们使用 Prism MVVM,在 DI 服务上下文中,我们保留了一个实时数据上下文,用于跟踪用户通过 wpf 前端和服务显示和编辑的实体。
  2. 为了实现“撤消”功能,我们使用以下方法跟踪对象 entity.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotificationsWithOriginalValues);

在编辑时,对象会更新,在 Reload() 时,它会从跟踪的原始值恢复。就对象而言,操作还可以,但是,wpf 方面却无法正常工作。似乎 ef.net 核心是 wpf 应用程序的一个非常不适应的公民,假设它是 INotifyPropertyChanged 机制的唯一受益者。当然,这对于 WPF 来说一点也不真实。

  1. EF.net 在加载、重新加载等时似乎不使用属性。它直接作用于基础字段。因此,NotifyPropertyChanged 永远不会触发,因此网格永远不会用新数据刷新,比如dbContext.Entry(c).Reload();。那么问题 #1,有没有办法强制 ef.net 使用属性而不是字段?
  2. INotifyPropertyChanged 的 ef.net 实现似乎存在缺陷。如果您在属性上调用 PropoertyChanged 事件,而不实际更改它,它会将实体标记为Modified,即使它可以轻松比较原始值和当前值。这禁止我们手动引发属性更改事件来控制 WPF 呈现。不知道如何解决这个问题,或者它是否可以解决,因为它只适用于这个跟踪策略。我愿意接受有关如何在不激怒 ef.net 的情况下通知 WPF 元素的任何建议。
  3. 确定对象的状态是相当复杂的操作,涉及dbContext.Entry(entry).State,它存在于DataContext 层次结构内的任何WPF 绑定之外。它使绑定状态几乎不可能(例如更改脏条目的背景或显示保存按钮等)。我们通过从处理INotify* 实现并保留[NotMapped] bool IsDirty 标志的NotifySetterObject 基类继承我们所有的实体类来“解决”它。不用说,我非常不喜欢这样,保留两个未链接的州旗听起来像是一场等待发生的事故。我想知道您是否遇到过类似的问题,以及您是否设计了一个更好、更理智的解决方案。

EF.net 似乎从框架 ef.net 发生了重大变化,因为它只非常适合分离的上下文场景(如 asp.net)。我们是否在这里浪费时间试图将这双鞋穿在 wpf 上?我们是否应该专注于更适合现场环境的不同 OR 引擎?

【问题讨论】:

    标签: wpf entity-framework ef-core-3.0 wpf-core wpf-core-3.0


    【解决方案1】:

    在尝试解决您的问题之前,让我指出一些事情:

    1. 您使用的是 EF Core 3.0,该版本目前处于预览版(测试版),因此很多事情可能无法按预期工作。

    2. 如果 ef.net 指的是 EF6,即您要移植的旧项目使用的是 EF6,则没有必要切换到 EF Core - EF6 也是 getting .Net Core support - 预览 em> 版本is available here

    现在关于您的具体问题:

    1. EF Core 可以使用属性、字段或两者。这可以通过 fluent API 在上下文、实体和属性级别进行配置。只是 EF Core 3.0 默认值已更改 - 您可以在 Breaking Changes - Backing fields are used by default 中看到。该链接还显示了如何通过使用获得所需的行为

      .UsePropertyAccessMode(PropertyAccessMode.FieldDuringConstruction)
      

    在模型(所有实体)、实体(所有实体属性)或属性(特定实体属性)构建器上。

    1. ChangeTrackingStrategy 文档中解释了该行为:

    当实体提出PropertyChanging 时记录原始值。当实体引发PropertyChanged 事件时,属性被标记为已修改。

    这是设计使然,因此您无能为力。但是解决 #1 消除了手动引发 PropertyChanged 事件的需要,并且双向绑定似乎完美无缺。

    1. 我不太清楚你到底想干什么。但是从 v2.1 开始,EF Core 在ChangeTracker - TrackedStateChanged 上提供了两个State change events,它们(尤其是第二个)可用于提供状态更改通知。但实际的机制是留给你的。例如,您可以使用 EF Core 2.1+ 的entity constructor service injection 功能将DbContext 注入到实体中,然后实体可以订阅StateChanged 事件并为其自己未映射的State 属性等引发PropertyChanged

    【讨论】:

    • 关于最初的 cmets:我们在 Framework/EF6 上有点失去了 MS 对 TLC 的感觉,因此我们决定将所有内容都移植到内核中,我们不想陷入糟糕的境地。核心中还有其他功能不会被反向移植到 EF6 中,我们的目标是尽可能使用它们。
    • 剩下的,首先感谢#1,这确实解决了问题。在 3 上,我们需要一种方法来绑定实体状态(从源的一种方式)并在更改时接收通知(如 INotify*)。理论上,我可以多重绑定到当前实体和上下文,并使用 multibindingconverter 调用dbcontext.Entry(e).Status。但它是一招一式的小马,如果状态发生变化,则没有导致重新绑定的通知路径。
    • 但是前面提到的Context.ChangeTracker.StateChanged 应该会给你那个通知,不是吗?
    • 是的,同一个想法的不同实现。所以 EF Core 一点也不差:)
    • 是的,这是我现在可以使用的东西。谢谢!
    猜你喜欢
    • 2017-12-09
    • 1970-01-01
    • 2011-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2021-08-13
    相关资源
    最近更新 更多