使用 Castle Windsor 的存储库类的适当生命周期
当我开始使用 Windsor 时,我认为 DI 会很简单。现在它让我越来越困惑。
存储库给我的印象是一个具有单例生命周期的类。我应该有一个 FooRepository 的单个实例,以便在应用程序的生命周期内加载 Foos 并将其保存到数据库中。
但是,每个存储库都保存对 UnitOfWork 的引用,该引用执行脏检查、与数据库一起使用等。UnitOfWork 具有 PerWebRequest 的生命周期 - UnitOfWork 成为单例根本没有意义,因为单例实例可以(例如)同时刷新多个用户会话所做的更改。
因此,我有一个单例 FooRepository 保存对 UnitOfWork 的引用,该引用在会话结束时被释放!我什至不确定这会对存储库的行为产生什么影响,但这听起来不太好。
谁能用简单的英语(好吧,也许用一些代码)解释一下在 Web 应用程序中管理 Repository 和 UnitOfWork 类的生命周期的适当方法?
When I started with Windsor I thought DI would be simple. Now it's causing me more and more confusion.
A repository strikes me as a class with a singleton lifecycle. I should have a single instance of a FooRepository to load and save Foos to the database during the application's lifetime.
However, each repository holds a reference to a UnitOfWork, which does the dirty checking, works with the database etc. The UnitOfWork has a lifecycle of PerWebRequest - it makes no sense at all for the UnitOfWork to be a singleton, as a singleton instance could (for example) flush the changes made by several user sessions at the same time.
So then I have a singleton FooRepository holding a reference to a UnitOfWork, which at the end of the session gets disposed! I'm not even sure what effect that would have on the repository's behaviour, but it doesn't sound good.
Can anyone explain, in simple English (okay, maybe with some code), the appropriate way to manage the lifecycle of Repository and UnitOfWork classes in a web app?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
经验法则是——组件不应依赖于比它寿命更长的其他组件。
换句话说,瞬态依赖于单例或每个网络请求组件是可以的,但反之则不然。
我处理存储库 - UoW 场景的方式是我的 UoW 是针对每个 Web 请求的,但存储库是无状态且瞬态的。
Rule of thumb is - component should not depend on other components that will outlive it.
In other words, it's ok for transient to depend on singleton, or per-web-request component, but not the other way around.
The way I approach Repository - UoW scenario is my UoW is per web request, but repositories are stateless and transient.
当您说存储库时,我假设您指的是抽象 Nhibernate 会话的存储库。
如果是这样,那么它永远不应该是单例的。如果它是单例,那么多个请求线程将践踏彼此的会话。我个人发现这方面存在一些缺陷。由于 Castle 的默认生命周期是单例的,如果开发人员忘记显式标记组件的生命周期,就会发生不好的事情。
理想情况下,它应该是每个请求(遵循工作单元概念)。此方法的唯一附加条件是您已在应用程序中启用 Asp.net 兼容模式(如果不是 Asp.net)。另一种方法是将存储库标记为瞬态。但这种方法的缺点是每次组件需要时 Castle 都会实例化一个新的存储库对象。
When you say repository, I assume you mean a repository which abstracts an Nhibernate session.
If so, then it should never ever be singleton. If it is a singleton, then multiple request threads will trample over one another's session. I personally have seen a few defects around this. Since Castle's default life cycle is singleton, if a developer forgets to explicitly mark a component's life cycle, bad things start happening.
It should ideally be per-request (following the unit of work concept). The only rider to this approach is that you have enable Asp.net compatibility mode in your application (if it's not Asp.net that is). The other way is to mark a repository transient. But the downside to this approach is that Castle will instantiate a new repository object every time a component needs it.