背景:
我有一个基于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));