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

我的第一个真正的(不是测试)NHibernate / Castle.ActiveRecord项目正在迅速发展.

我正在使用NHibernate / Castle.ActiveRecord大约一个月,但仍然不知道如何在我的
WindowsForms应用程序中处理Sessions.

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

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

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

Qestions

>对于windowsforms / desktop-application,还有其他会话处理方法吗?
>我可以向所有演示者添加session-property或session-constructor-parameter,但是在我的ui-code上进行会话处理感觉不对.
>当一个异常发生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

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

>使用BoxSearchPresenter实例搜索并选择一个对象

>此用例的一部分是使用ProductSearchPresenter的实例来填充BoxSearchPresenter的条件
>此用例的一部分是使用BoxEditPresenter的实例来编辑和保存BoxSearchPresenter实例的选定对象

>使用UserSearchPresenter实例搜索并选择一个对象

>此用例的一部分是使用UserEditPresenter的实例来编辑和保存UserSearchPresenter的选定对象
>此用例的一部分是使用ProductSearchPresenter来搜索和选择将添加到User.AssignedProducts的对象.

>使用ProductSearchPresenter的实例来搜索和选择对象.

>此用例的一部分是使用ProductEditPresenter的实例来编辑和保存ProductSearchPresenter的选定对象.

它只是一小部分用例,但我已经遇到了很多问题.

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

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

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

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

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

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

那么回答你的问题:

>每个演示者的会话和每次会话的会话(也适用于WinForms)在这里只是真正可用的模式(并且在整个地方打开关闭会话,但不是真正好的方法来处理) –
>最好通过使存储库依赖于会话而不是演示者来解决.您使演示者依赖于存储库,存储库依赖于会话,当您创建所有存储库时,您可以为它们提供公共会话;但正如我再次声明的那样,这只有在上下文中完成时才是实用的.您无法与演示者编辑发票和其他演示者编辑客户共享会话;但您可以在通过主演示者和发票详细信息以及发票备注子演示者编辑发票时共享会话.
>请澄清,不明白这个……

点赞