我知道过去曾提出过会话管理的问题,但我找不到任何可以帮助我解决问题的东西。
我有许多存储库类(例如 CustomerRepository、ProductRepository 等),我通过 Castle Windsor 解决了这些 问题(注意:我正在尝试应用概述的三个调用模式 此处)。我想我最好每个演示者都有一个会话(在我的例子中,这相当于每个表单一个会话),但是,存储库类需要访问当前活动表单的会话。我不确定如何合并这个事实上,这些存储库是通过温莎解析的,因为演示者不是单例。
例如:
public class SomePresenter
{
private ISomeView view;
private ISession session;
private ICustomerRepository customerRepository;
private IOrderRepository orderRepository;
public SomePresenter(ISomeView view, ISessionFactory sessionFactory, ICustomerRepository customerRepository, IOrderRepository orderRepository)
{
this.view = view;
this.session = sessionFactory.OpenSession();
this.customerRepository = customerRepository;
this.orderRepository = orderRepository;
}
}
存储库需要访问会话...我如何使用温莎来解决这个问题?我是否被迫通过属性手动设置存储库上的会话,或者是否存在我不熟悉的聪明的温莎技巧?
I know the question of session management has been brought up in the past, but I could not find anything that helps me overcome my problem..
I have a number of repository classes (e.g CustomerRepository, ProductRepository etc.) which I resolve through Castle Windsor (Note: I am trying to apply the three calls pattern as outlined here). I figure I'd best have a session per Presenter (in my case, this is equivalent to one per form), however, the repository classes need to access the session for the currently active form.. I am not sure how I incorporate this with the fact that these repositories are resolved through windsor, since presenters are not singletons..
For example:
public class SomePresenter
{
private ISomeView view;
private ISession session;
private ICustomerRepository customerRepository;
private IOrderRepository orderRepository;
public SomePresenter(ISomeView view, ISessionFactory sessionFactory, ICustomerRepository customerRepository, IOrderRepository orderRepository)
{
this.view = view;
this.session = sessionFactory.OpenSession();
this.customerRepository = customerRepository;
this.orderRepository = orderRepository;
}
}
The repositories needs access to the session... How do I go about this using Windsor? Am I forced to manually set the session on the repositories through a property, or is there a clever Windsor trick that I'm unfamiliar with?
发布评论
评论(2)
为什么不直接将
ISession
注入您的存储库而不是ISessionFactory
呢?下面是我在 Autofac(一种不同的 IoC 容器)中使用的类似代码:
其中
NHibernateContext
是我唯一一个配置 NHibernate 并保存ISessionFactory
单例的静态类。因此,我的存储库/查找对象请求会话:
然后我的演示者/视图模型/监督控制器/无论如何,我们本月调用它只是获取存储库或查找对象:
对于 Windsor,我我想(我对它的 API 不是很熟悉,你可能需要调整这个,但它应该给你一个想法)它会是这样的
,也就是说,你告诉容器,“当有人请求 ISession 时,运行这个小获取
ISessionFactory
并打开会话的委托,然后为他们提供该ISession
实例。”但是谁关闭
ISession
?这取决于您:您可以让存储库在其自己的Dispose()
方法中显式关闭ISession
。或者您可以依靠您的容器来完成关闭和处理;在 Autofac 中,我使用 ILifetimeScope 和 InstancePerLifetimeScope() 来完成此操作;在温莎,我相信您需要查找嵌套容器,这样当您处置子容器时,它创建的所有组件也会被处置。根据我的经验,这通常意味着容器至少会泄漏到我的应用程序的“主表单”中:当需要创建表单时,它会创建一个新的生命周期范围/嵌套容器并显示该表单。但低于这个级别的任何人都不知道容器;它只是在一组组件周围扔一个套索并说“当表单关闭时摆脱所有这些”。
(这是为了防止在大多数应用程序中仅使用一个大喇叭
ISession
。这在 ASP.NET 中工作得很好,每个请求一个会话,但在 Windows 窗体中,正如您所注意到的,它是就像针对陈旧对象异常的定时炸弹一样。对于每个“工作单元”(通常是每个表单或服务)来说,拥有自己的ISession
会更好。)您也可以设计存储库,以便每个方法都可以使用。需要传入
ISession
,但这似乎会变得乏味。希望能给你一些想法。祝你好运!
Why not just inject an
ISession
into your repositories instead of anISessionFactory
?Here is the similar code that I use with Autofac, a different IoC container:
where
NHibernateContext
is my one and only static class that configures NHibernate and holds onto anISessionFactory
singleton.So my repository/lookup object asks for a session:
Then my Presenter/View Model/Superivsing Controller/Whatever-The-Heck-We're-Calling-It-This-Month just gets the repository or lookup object:
For Windsor, I think (I'm not terribly familiar with its API, you may have to tweak this but it should give you an idea) it would be something like
That is, you tell the container, "When somebody asks for an ISession, run this little delegate that gets the
ISessionFactory
and opens a session, then give them thatISession
instance."But who closes the
ISession
? It's up to you: you could have the repository explicitly close theISession
in its ownDispose()
method. Or you could rely on your container to do the closing and disposing; in Autofac, I do this withILifetimeScope
andInstancePerLifetimeScope()
; in Windsor, I believe you need to look up nested containers, such that when you dispose a child container, all of the components it created are also disposed.In my experience, this usually means that the container leaks into at least the "main form" of my application: when it's time to create a form, it creates a new lifetime scope/nested container and shows the form. But nothing below this level knows about the container; it's just to throw a lasso around a set of components and say "get rid of all of these when the form is closed."
(This is to prevent just one big honking
ISession
from being used throughout most of the application. That works fine in ASP.NET, one session per request, but in Windows Forms, as you note, it is like a ticking time bomb for stale object exceptions. Better for each "unit of work" (typically, each form or service) to have its ownISession
.)You could alternatively design your repositories such that each method requires an
ISession
to be passed in, but that seems like it'd get tedious.Hope that gives you some ideas. Good luck!
为什么不为每个演示者/控制器提供一个带有单独的数据访问对象 (DAO) 的
SessionProvider
?您的模型是通过每个数据访问对象
访问的。Why not just have one
SessionProvider
with individualData Access Objects
(DAO) for each presenter/controller? Your model is accessed through eachData Access Object
.