2

我在由 SQL CE 数据库支持的 WPF MVVM 应用程序中使用实体框架和代码优先方法。我正在尝试设计一个模型类,它可以简单地更新它的一个属性值以响应另一个属性值的变化。基本上,我正在寻找一种在 EF 初始化实例后定义“自我跟踪”的 poco 的方法。如果答案涉及放弃 Code First,那么也许这是唯一可行的途径(不确定)。一个基本的例子:

class ThingModel
{
    public int Id { get; set; }

    public bool OutsideDbNeedsUpdate { get; set; }

    private string _foo;

    public string Foo
    {
        get { return _foo; }

        set
        {
            if (_foo != value)
            {
                _foo = value;

                OutsideDbNeedsUpdate = true;
            }
        }
    }
}

但是,上述问题在于,每当 DbContext 在运行时初始化实例并设置字段时,我的类都会过早地设置依赖字段作为响应。换句话说,我正在寻找一种简单的模式,它允许我的 poco 类仅在 EF 完成实例上的字段初始化后才进行这种特殊的更改跟踪。

我意识到我可以在此处执行类似解决方案的操作, 但我的业务案例要求将此特殊更改跟踪与 EF 更改跟踪分离,换句话说,无论上面的 HasChanges 属性的状态如何,我都需要 SaveChanges 的能力。这是因为我希望能够定期检查我的实体上的 HasChanges 属性,进而更新外部数据库中的依赖值(与支持 EF DbContext 的数据库不同),并且 EF DB 之间可能会发生许多更改/保存推到外部数据库。因此,我希望将标志与我的数据库中的记录一起保存,并在对外部数据库进行定期更新时将其重置为 false。

4

1 回答 1

2

编辑后,我认为您可以使用ObjectMaterialized 事件

在对象上设置了所有标量、复杂和引用属性之后,但在加载集合之前引发此事件。

把它放在你的构造函数中DbContext

((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized +=
    HandleObjectMaterialized;

和方法:

private void HandleObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
{ }

现在的问题是,在方法体中放什么?可能最简单的解决方案是定义一个接口

interface IChangeTracker
{
    bool Materialized { get; set; }
    bool OutsideDbNeedsUpdate { get; }
}

并让您要跟踪的类实现此接口。

然后,HandleObjectMaterialized你可以这样做:

var entity = e.Entity as IChangeTracker;
if (entity != null)
{
    entity.Materialized = true;
}

在此之后,您知道何时可以在OutsideDbNeedsUpdate内部进行设置。


原文

通常不建议使用具有副作用的属性(嗯,更准确地说,具有比更改表示的状态更多的副作用)。也许这条规则有例外,但大多数时候在属性之间建立依赖关系并不是一个好主意。

我必须猜测一下您最擅长的事情,因为我不知道您的真实代码是关于什么的,但是可以将逻辑放在 getter 中。只是一个例子:

public State State
{
   get { return this.EndDate.HasValue ? MyState.Completed : this._state; }
   set { this._state = value; }
}

这不会消除相互依赖关系,但会将生效时间推迟到访问属性的时间。在您的情况下,这可能不会早于SaveChanges().

另一种策略是制作一种同时设置两个属性的方法。方法预计会产生副作用,尤其是当它们的名称清楚地表明它时。你可以有一个像SetMasterAndDependent (string master).

现在方法在数据绑定场景中并不方便。在这种情况下,您最好让视图模型设置两个属性或调用上述方法。

于 2013-01-16T22:59:26.283 回答