当另一个属性更改时(在初始化实体之后)更新实体属性

时间:2013-01-16 16:56:10

标签: c# wpf entity-framework code-first

我在由SQL CE数据库支持的WPF MVVM应用程序中使用Entity Framework和Code First方法。我正在尝试设计一个模型类,它可以简单地更新其中一个属性值,以响应其中一个属性值的变化。基本上,我正在寻找一种方法来定义在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完成初始化实例上的字段后才能进行这种特殊的更改跟踪。

我意识到我可以做类似解决方案的事here 但是我的业务案例要求这个特殊的变更跟踪与EF变更跟踪分离,换句话说,无论上面的HasChanges属性如何,我都需要具有SaveChanges的能力。这是因为我希望能够定期检查我的实体上的HasChanges属性,然后更新外部数据库中的相关值(不是支持EF DbContext的相同值),并且可能会在EF DB之间发生许多更改/保存推到外面的DB。因此,我希望在我的数据库中保留带有记录的标志,并在定期更新外部数据库时将其重置为false。

1 个答案:

答案 0 :(得分:2)

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

  

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

将它放在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)等方法。

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