Background:
I have a custom user control based around a WPF TreeView. I've been using the MVVM pattern and have a base view model TreeNode
class and several derived view models such as LocationNode, LocationFolder, PersonNode, PersonFolder, CollectionNode, CollectionFolder, etc..
背景:我有一个基于WPF TreeView的自定义用户控件。我一直在使用MVVM模式,并有一个基本视图模型TreeNode类和一些派生的视图模型,如LocationNode、LocationFolder、PersonNode、PersonFolder、CollectionNode、CollectionFolder等。
A example of how the tree might be laid out is:
这棵树的布局的一个例子是:
- CollectionFolder
--> CollectionNode
--> LocationFolder
-->LocationNode
-->LocationNode
--> PersonFolder
-->PersonNode
--> CollectionNode
--> CollectionNode
+ CollectionFolder
+ CollectionFolder
When I perform drag and drop operations, each class handles the business logic, i.e. if I drop on a PersonNode
on a CollectionNode
, the CollectionNode
view model contains the logic how on to add the PersonNode
it its child PersonFolder
.
当我执行拖放操作时,每个类都处理业务逻辑,例如,如果我在集合节点上的PersonNode上拖放,那么CollectionNode视图模型包含如何将PersonNode添加到它的子PersonFolder中的逻辑。
Problem:
Everything works great, I can drag and drop all over the place, and the code is nicely contained in the dervied classes. If I need to add an extra drop rule, I add it to the appropriate drop target view model.
问题:一切都很好,我可以到处拖放,代码很好地包含在dervied类中。如果我需要添加一个额外的drop规则,我将它添加到适当的drop目标视图模型中。
The problem is when a PersonNode
is added to a PersonFolder
I need to create a new database entry to reflect that the underlying Person
model is now in also in a new Collection
.
问题是,当一个PersonNode被添加到PersonFolder中时,我需要创建一个新的数据库条目来反映底层的Person模型现在也在一个新的集合中。
Currently, each view model in the tree has access to the current database session/transaction and can perform the insert/save. But this makes catching exceptions and errors extremely repeative, my exception handling code is being duplicated all over my view models. Is there a better way in MVVM to handle my database interactions?
当前,树中的每个视图模型都可以访问当前的数据库会话/事务,并可以执行插入/保存。但是这使得捕获异常和错误变得极其简单,我的异常处理代码在我的视图模型中被复制。MVVM中是否有更好的方法来处理数据库交互?
An code snippet from my Drop
event in my PersonFolder
我的个人文件夹中的Drop事件的代码片段
// 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] and [2] have the potential for throwing exceptions and should be handled in try/catch statements. However, I don't want to duplicate all my exception handling in all my view models, any suggestions?
[1]和[2]有可能抛出异常,应该在try/catch语句中处理。但是,我不想在我所有的视图模型中复制所有的异常处理,有什么建议吗?
I guess I could always implement a singleton to contain the session and exception handling and pass my new entities into that?
我想我总是可以实现一个单例来包含会话和异常处理,并将我的新实体传递给它?
1 个解决方案
#1
1
I'm assuming that the variable part of your last code block is:
我假设你最后一个代码块的变量是:
_uow.Add( entry );
...so in some cases you might actually want significantly more or less actions to happen in that spot.
…所以在某些情况下,你可能会想要在那个地方发生很多或多或少的行动。
I think this is a good candidate for the "Hole in the Middle Pattern".
我认为这是“中间模式的漏洞”的一个很好的候选者。
Basically just pass an
基本上只是通过
Action<T>
to some other place (Singleton, whatever) that opens a transaction, passes the context (_uow) to your action, and then commits the transaction, and handles all your exception logic. Your code would look like:
将上下文(_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));
#1
1
I'm assuming that the variable part of your last code block is:
我假设你最后一个代码块的变量是:
_uow.Add( entry );
...so in some cases you might actually want significantly more or less actions to happen in that spot.
…所以在某些情况下,你可能会想要在那个地方发生很多或多或少的行动。
I think this is a good candidate for the "Hole in the Middle Pattern".
我认为这是“中间模式的漏洞”的一个很好的候选者。
Basically just pass an
基本上只是通过
Action<T>
to some other place (Singleton, whatever) that opens a transaction, passes the context (_uow) to your action, and then commits the transaction, and handles all your exception logic. Your code would look like:
将上下文(_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));