背景:
我有一个基于WPF TreeView的自定义用户控件。我一直在使用MVVM模式,并具有一个基本 View 模型TreeNode类和一些派生的 View 模型,例如LocationNode, LocationFolder, PersonNode, PersonFolder, CollectionNode, CollectionFolder, etc..
树的布局示例如下:


- CollectionFolder
--> CollectionNode
    --> LocationFolder
        -->LocationNode
        -->LocationNode
    --> PersonFolder
        -->PersonNode
--> CollectionNode
--> CollectionNode
+ CollectionFolder
+ CollectionFolder

当我执行拖放操作时,每个类都会处理业务逻辑,即,如果我将PersonNode放在CollectionNode上,则CollectionNode View 模型将包含如何将PersonNode添加为其子PersonFolder的逻辑。

问题:
一切都很好,我可以在所有地方拖放,并且代码很好地包含在派生类中。如果需要添加额外的放置规则,请将其添加到适当的放置目标 View 模型中。

问题是当将PersonNode添加到PersonFolder时,我需要创建一个新的数据库条目以反射(reflect)基础Person模型现在也位于新的Collection中。

当前,树中的每个 View 模型都可以访问当前数据库的 session /事务,并且可以执行插入/保存。但是,这使得捕获异常和错误变得非常重复,我的异常处理代码在我的所有 View 模型中都重复了。 MVVM中是否有更好的方法来处理数据库交互?

我的Drop中的PersonFolder事件的代码段

// Create a new view model for the Person and add it to my children
_children.Add( new PersonNode( droppedPerson ) );

// Create a new entry in the collection for this person
CollectionEntry entry = new CollectionEntry();
entry.Entity = droppedPerson;
entry.Collection = _collection;

// Save the new entry
using( var transaction = _uow.BeginTransaction( IsolationLevel.Serializable ) )
{
    // Add the entry to the session
    _uow.Add( entry );

    // Save the session
    _uow.SaveChanges(); // [1]

    // Commit transaction
    transaction.Commit(); // [2]
}

[1]和[2]有引发异常的可能性,应在try/catch语句中进行处理。但是,我不想在所有 View 模型中重复所有异常处理,有什么建议吗?

我想我总是可以实现一个单例来包含 session 和异常处理,并将我的新实体传递给其中?

最佳答案

我假设您最后一个代码块的可变部分是:

_uow.Add( entry );

...因此,在某些情况下,您实际上可能希望在该位置执行更多或更少的操作。

我认为这是“Hole in the Middle Pattern”的不错选择。

基本上只是通过
Action<T>

到其他打开事务的地方(Singleton,无论如何),将上下文(_uow)传递给您的操作,然后提交事务,并处理所有异常逻辑。您的代码如下所示:

// Create a new view model for the Person and add it to my children
_children.Add( new PersonNode( droppedPerson ) );

// Create a new entry in the collection for this person
CollectionEntry entry = new CollectionEntry();
entry.Entity = droppedPerson;
entry.Collection = _collection;

someSingleton.Execute(o => o.Add(entry));

08-18 14:39
查看更多