4

我的第一个真实(非测试)NHibernate/Castle.ActiveRecord 项目正在快速发展。我正在使用 NHibernate/Castle.ActiveRecord 大约一个月,但仍然不知道如何在我的 WindowsForms 应用程序中处理会话。

常见的处理方法对我不起作用:

  • SessionPerRequest、SessionPerConversation 等都只适用于 WebApplications 等。
  • 当我正确时,不推荐 SessionPerApplication/高度危险
  • SessionPerThread 不是很有帮助,因为我要么只有一个线程,即 WindowsForms 线程,要么为每个按钮单击一个新线程。第一件事会让我的应用程序使用太多内存并将旧对象保存在内存中。使用 ech 按钮单击的工作线程,我将禁用延迟加载,因为我加载的对象的寿命会比线程长。
  • SessionPerPresenter 不能正常工作,因为它很常见,我在表单中打开一个“子演示者”,让用户搜索/加载/选择一些引用的对象(外键)并且导致演示者被破坏 - 什么意思会话关闭 - 但在“超级演示者”中使用的对象填充引用属性(外键)。

我已经使用谷歌和必应几个小时并阅读了很多,但只找到了一个关于我的案例的好网站:http: //msdn.microsoft.com/en-us/magazine/ee819139.aspx。使用了 SessionPerPresenter,但对于“子演示者”,它只给出了 id,而不是整个对象!并且它接缝在这个例子中没有外键,也没有将对象返回给“超级演示者”的场景。

问题

  1. windowsforms/桌面应用程序是否有其他会话处理方法?
  2. 我可以为我的所有演示者添加会话属性或会话构造器参数,但是在我的 ui 代码中进行会话处理感觉不对。
  3. 当发生异常时 NHibernate 想要我终止会话。但是,如果它“只是”一个业务逻辑异常而不是 NHibernate-Exception?

例子

我试图举一个例子来涵盖我的大部分问题。

// 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

现在我有以下用例,所有这些都可以在同一个应用程序中同时异步执行(使用只是在演示者之间切换)。

  1. 使用 BoxSearchPresenter 的实例来搜索和选择对象
    1. 这个用例的一部分是使用 ProductSearchPresenter 的实例来填充 BoxSearchPresenter 的条件
    2. 这个用例的一部分是使用 BoxEditPresenter 的实例来编辑和保存 BoxSearchPresenter-instance 的选定对象
  2. 使用 UserSearchPresenter 的实例来搜索和选择对象
    1. 这个用例的一部分是使用 UserEditPresenter 的实例来编辑和保存 UserSearchPresenter 的选定对象
    2. 这个用例的一部分是使用 ProductSearchPresenter 来搜索和选择将添加到 User.AssignedProducts 的对象。
  3. 使用 ProductSearchPresenter 的实例来搜索和选择一个对象。
    1. 这个用例的一部分是使用 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。
4

1 回答 1

2

这只是我发现最适合我们的 WinForms 应用程序架构(基于 MVP)的简短视图。

每个演示者都是依赖于它需要的存储库的构造函数,例如,如果您有 InvoicePresenter,那么您将 InvoiceRepository 作为依赖项,但您可能会有 CustomerRepository 和许多其他依赖于复杂性(如果您想将所有客户加载到客户组合框中,CustomerRepsitory更改发票的客户,诸如此类)。

然后,每个存储库都有一个 UnitOfWork 的构造函数参数。您可以使用 UnitOfWork 模式抽象会话,也可以让您的存储库依赖于 ISession。

一切都由 IoC 容器连接在一起,我们在其中基于“上下文”创建演示者。这是一个非常简单的概念,上下文是每个演示者和所有子演示者,反过来我们将其创建为更复杂的演示者的复合块以降低复杂性(例如,如果您有多个选项选项卡来编辑某些实体或其他内容)。

因此,在实践中,此上下文 90% 是基于时间形式的,因为一种形式至少是一个演示者/视图。

所以回答你的问题:

  1. 每个演示者的会话和每个对话的会话(也适用于 WinForms)在这里只是真正可用的模式(并且在整个地方打开关闭会话,但不是处理这种情况的真正好方法) -

  2. 这最好通过使存储库依赖于会话而不是演示者来解决。你让演示者依赖于存储库,存储库依赖于会话,当你创建所有时,你给他们一个公共会话;但正如我再次声明的那样,这只有在上下文中完成时才实用。您不能共享主讲者编辑发票和另一个主讲者编辑客户的会话;但是您可以在通过主演示者和发票详细信息以及发票注释子演示者编辑发票时共享会话。

  3. 求解释,没看懂。。。

于 2012-01-13T19:12:34.417 回答