我的第一个真正的(不是测试的)NHibernate/CaSTLe.ActiveRecord 项目正在快速开发。 我现在正在使用 NHibernate/CaSTLe.ActiveRecord 大约一个月,但仍然不知道如何在我的 WindowsForms 应用程序中处理 session 。
常见的处理方法对我来说不起作用:
- SessionPerRequest、SessionPerConversation 等都仅适用于 WebApplications 等。
- 当我正确时,SessionPerApplication 不被推荐/非常危险
- SessionPerThread 不是很有帮助,因为我要么只有一个线程(WindowsForms 线程),要么为每个按钮单击一个新线程。第一件事会让我的应用程序使用太多内存并在内存中保存旧对象。通过单击 ech 按钮的工作线程,我将禁用延迟加载,因为我加载的对象的生命周期比线程长。
- SessionPerPresenter 也不起作用,因为很常见,我在表单中打开一个“子演示者”,让用户搜索/加载/选择一些引用的对象(外键),并且导致演示者被破坏- session 关闭是什么意思 - 但“ super 演示者”中使用的对象来填充引用属性(foreigen key)。
我已经使用谷歌和必应几个小时并阅读了很多内容,但只找到了一个关于我的案例的好网站:http://msdn.microsoft.com/en-us/magazine/ee819139.aspx 。这里使用了 SessionPerPresenter,但对于“子演示者”来说,它只给出了 id,而不是整个对象!看起来这个例子中没有外来键,也没有将对象返回到“ super 呈现者”的场景。
问题
- Windowsforms/桌面应用程序还有其他 session 处理方法吗?
- 我可以向我的所有演示者添加 session 属性或 session 构造函数参数,但在我的 ui 代码中进行 session 处理感觉不太合适。
- 当发生异常时,NHibernate 希望我终止 session 。但如果它“只是”业务逻辑异常而不是 NHibernate 异常呢?
示例
我试图举一个例子来涵盖我的大部分问题。
// The persisten classes
public class Box
{
public virtual int BoxId{get;set;}
public virtual Product Content{get;set;}
...
}
public class User
{
public virtual int UserId{get;set;}
public virtual IList<Product> AssigenedProducts{get;set;}
...
}
public clas Product
{
public virtual int ProductId{get;set;}
public virtual string PrductCode{get;set;}
}
.
// The presenter-classes
public class ProductSearchPresenter : SearchPresenter<Product> { ... }
public class ProductEditPresenter : EditPresenter<Product> { ... }
public class UserSearchPresenter : SearchPresenter<User> { ... }
public class UserEditPresenter : EditPresenter<User> { ... }
public class BoxSearchPresenter : SearchPresenter<Box> { ... }
public class BoxEditPresenter : EditPresenter<Box> { ... }
// The search-presenters allow the user to perform as search with criterias on the class defined as generic argument and to select one of the results
// The edit-presenters allow to edit a new or loaded (and given as parameter) object of the class defined as generic argument
现在我有以下用例,所有用例都可以在同一个应用程序中同时异步执行(使用只需在演示者之间切换)。
- 使用 BoxSearchPresenter 实例来搜索并选择对象
- 此用例的一部分是使用 ProductSearchPresenter 的实例来填充 BoxSearchPresenter 的条件
- 此用例的一部分是使用 BoxEditPresenter 的实例来编辑和保存 BoxSearchPresenter 实例的选定对象
- 使用 UserSearchPresenter 实例来搜索并选择对象
- 此用例的一部分是使用 UserEditPresenter 的实例来编辑和保存 UserSearchPresenter 的选定对象
- 此用例的一部分是使用 ProductSearchPresenter 搜索并选择将添加到 User.AssignedProducts 的对象。
- 使用 ProductSearchPresenter 实例搜索并选择对象。
- 此用例的一部分是使用 ProductEditPresenter 的实例来编辑和保存 ProductSearchPresenter 的选定对象。
这只是一小部分用例,但我已经遇到了很多问题。
- 用例 1. 和 2. 在同一个 ui 线程中同时运行。
- 用例 1.1。和2.2。将选定的对象返回给其他演示者,这些演示者使用该对象的时间比已加载该对象的演示者存在的时间长。
- 用例 3.1。可能会改变从 2.2./1.1 加载的对象。 3.1之前。开始了,但是当2.2./1.1.在 3.1 之前提交。完成后,对象将被保存,并且不可能“回滚”3.1。
最佳答案
这只是我发现最适合我们的 WinForms 应用程序架构(基于 MVP)的简短 View 。
每个演示者都是依赖于它需要的存储库的构造函数,例如,如果您有 InvoicePresenter,那么您有 InvoiceRepository 作为依赖项,但您可能会有 CustomerRepository 和许多其他依赖项,具体取决于复杂性(CustomerRepsitory 用于将所有客户加载到客户组合框中,如果您想更改发票的客户,诸如此类)。
然后,每个存储库都有一个 UnitOfWork 的构造函数参数。您可以使用 UnitOfWork 模式抽象 session ,也可以让您的存储库依赖于 ISession。
一切都通过 IoC 容器连接在一起,我们在其中根据“上下文”创建演示者。这是一个非常简单的概念,上下文是每个演示者和所有子演示者,我们又将其创建为更复杂的演示者的复合 block 以降低复杂性(例如,如果您有多个选项卡来编辑某些实体或其他内容)。
因此,在实践中,此上下文 90% 的时间是基于表单的,因为一个表单至少是一个演示者/ View 。
回答你的问题:
每个演示者的 session 和每个对话的 session (也适用于 WinForms)在这里只是真正可用的模式(并且在各处打开结束 session ,但不是处理该问题的好方法)-
最好的解决方法是使存储库依赖于 session ,而不是演示者。您使演示者依赖于存储库,存储库依赖于 session ,当您创建所有存储库时,您为它们提供公共(public) session ;但正如我再次指出的,这只有在上下文中完成时才实用。您不能共享演示者编辑发票的 session 和另一演示者编辑客户的 session ;但您可以在通过主演示者和发票详细信息以及发票注释子演示者编辑发票时共享 session 。
请澄清一下,不明白这个...
关于winforms - NHibernate/CaSTLe.ActiveRecord ; session 管理;窗体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8739457/