NHibernate / Castle.ActiveRecord;会话管理;的WinForms

时间:2012-01-05 08:13:37

标签: winforms nhibernate desktop-application castle-activerecord session-management

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

常见的处理方法不适合我:

  • SessionPerRequest,SessionPerConversation等仅适用于WebApplications等。
  • 当我正确
  • 时,SessionPerApplication不会重新编目/非常危险
  • SessionPerThread不是很有用,因为我要么只有一个线程,WindowsForms-thread,要么每个按钮点击一个新线程。第一件事会让我的应用程序使用太多内存并将旧对象保存在memmory中。使用ech按钮的工作线程单击我将禁用延迟加载,因为我加载的对象将比线程更长寿。
  • SessionPerPresenter工作不正常,因为我在表单中打开一个“sub-presenter”,让用户搜索/加载/选择一些引用的对象(foreigen key)并导致演示者被销毁是很常见的 - 什么意味着会话关闭 - 但“超级演示者”中使用的对象填充引用属性(foreigen key)。

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

Qestions

  1. 是否还有其他的windowsforms / desktop-application会话处理方法?
  2. 我可以为所有演示者添加会话属性或会话构造函数参数,但是在我的ui代码中进行会话处理感觉不对。
  3. 当一个异常发生时,NHibernate希望我杀死会话。但是,如果它只是'业务逻辑异常而不是NHibernate-Exception?
  4. 示例

    我试图在我的大部分问题上做一个例子。

    // 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的选定对象。
    4. 这只是一小部分用例,但我已经遇到很多问题。

      • UseCase 1.和2.在同一个ui-thread中同时运行。
      • UseCase 1.1。和2.2。将所选对象返回给使用此对象的其他演示者,然后存在已加载对象的演示者。
      • UseCase 3.1。可能会改变从2.2./1.1加载的对象。在3.1之前。开始了,但是当2.2./1.1。是在3.1之前提交的。完成后,对象将被保存,并且无法“回滚”3.1。

1 个答案:

答案 0 :(得分:2)

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

每个演示者都是依赖于它所需的存储库的构造函数,例如,如果您有InvoicePresenter,那么您将InvoiceRepository作为依赖项,但您可能拥有CustomerRepository以及许多其他依赖于复杂性的用户(CustomerRepsitory用于将所有客户加载到客户组合框中,如果你想改变发票的客户,这样的东西。)

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

IoC容器将所有内容连接在一起,我们根据“上下文”创建演示者。这是一个非常简单的概念,上下文是每个演示者和所有子演示者,我们创建为更复杂的演示者的复合块,以减少复杂性(例如,如果您有多个选项选项卡来编辑某个实体或某事)。

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

所以回答你的问题:

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

  2. 最好通过使存储库依赖于会话而不是演示者来解决。您使演示者依赖于存储库,存储库依赖于会话,当您创建所有存储库时,您可以为它们提供公共会话;但正如我再次声明的那样,这只有在上下文中完成时才是实用的。您无法与演示者编辑发票和其他演示者编辑客户共享会话;但您可以在通过主演示者和发票明细以及发票说明子演示者编辑发票时分享会话。

  3. 请澄清,不明白这一点......