NHibernate ISession 生命周期;什么时候可以在每个存储库方法中创建/处置?
我正在使用单层、单用户应用程序和FluentNHibernate。具有多个线程,由时间触发器和传入套接字消息触发器触发。
哪些要求将决定我是否可以在存储库的每个方法中创建/处置 ISession,或者是否需要通过多次调用(也许从程序开始到结束)维护 ISession 生命周期?
例如,延迟加载是否需要维护会话?如果我不使用延迟加载,我应该出于什么其他原因维护 ISession?
目前我的存储库方法如下所示,但我想知道我是否做错了。
public class ProductRepository
{
public void Delete(Product product)
{
using (ISession session = FNH_Manager.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Delete(product);
transaction.Commit();
}
}
}
class FNH_Manager
{
private static Configuration cfg;
private static ISessionFactory sessionFactory;
public static void ConfigureSessionFactory()
{
sessionFactory = CreateSessionFactory();
}
public static ISession OpenSession()
{
return sessionFactory.OpenSession();
}
EDIT1: 尝试处理“每次调用的会话”:
public class EmployeeRepository
{
public static void Delete(Employee employee)
{
using (ISession session = FNH_Manager.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
if (Employee.Id != 0)
{
var emp = session.Get(typeof(Employee), employee.Id);
if (emp != null)
{
session.Delete(emp);
transaction.Commit();
}
}
}
}
}
I'm working with single-tier, single-user applications, with FluentNHibernate. With multiple threads, triggered by time triggers and incoming socket message triggers.
What requirements will determine if I can create/dispose the ISession inside each method of the repositories, or if I need to maintain the ISession lifecycle over multiple calls, maybe from program start to end?
For example, does lazy-load require session to be maintained? And if I don't use lazyload, for what other reason should I maintain the ISession?
Currently my repository methods look like below, but I wonder if I'm doing it wrong..
public class ProductRepository
{
public void Delete(Product product)
{
using (ISession session = FNH_Manager.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Delete(product);
transaction.Commit();
}
}
}
class FNH_Manager
{
private static Configuration cfg;
private static ISessionFactory sessionFactory;
public static void ConfigureSessionFactory()
{
sessionFactory = CreateSessionFactory();
}
public static ISession OpenSession()
{
return sessionFactory.OpenSession();
}
EDIT1:
Attempt to handle "session per call":
public class EmployeeRepository
{
public static void Delete(Employee employee)
{
using (ISession session = FNH_Manager.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
if (Employee.Id != 0)
{
var emp = session.Get(typeof(Employee), employee.Id);
if (emp != null)
{
session.Delete(emp);
transaction.Commit();
}
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您引用延迟加载字段时,会话必须打开,因此,如果您依赖存储库外部的延迟加载,则需要在更高的位置管理会话生命周期。
如果不使用延迟加载,还存在是否需要在一个事务中支持多个操作的问题。例如,如果您一次性删除一个产品和一些其他数据,您希望在同一会话的一个事务中发生这种情况(否则您可能会删除该产品,让某些代码抛出一些异常,并且永远不会删除其他数据)数据,最终可能会出现孤立记录或数据库中的损坏状态)。
The session must be open when you reference a lazy-loaded field, so if you're relying on lazy-loading outside of your repository you'll need to manage the session lifespan somewhere higher up.
If you don't use lazy-loading, there's also the matter of whether you need to support multiple actions in one transaction. For example, if you delete a product AND some other data in one go, you'd want that to happen in one transaction in the same session (otherwise you might delete the product, have some code throw some exception, and never delete the other data, which may end up with orphan records or a corrupt state in your database).
我认为你应该为每个线程使用 UnitOfWork 模式。
在线程开始时创建
ISession
并用它初始化UnitOfWork
。存储库将UnitOfWork
与该信号ISession
结合使用。在线程执行结束时提交更改,如果与其他线程发生冲突则回滚。I think you should use UnitOfWork pattern per thread.
On thread start create
ISession
and initializeUnitOfWork
with it. Repositories useUnitOfWork
with that signleISession
. At the end of thread execution commit the changes or rollback if there was conflict with other threads.产品被删除时不与任何会话关联。它是一个所谓的分离对象。要在会话中使用它(例如删除它),您需要首先将其与当前打开的会话关联。有多种方法可以实现此目的:
ISession.Get()
或ISession.Load()
。ISession.Lock()
将对象重新附加到新打开的会话session
,否则您可能会遇到
StaleStateException
等。请记住阅读 NHibernate 文档
The Product is not associated with any session when beeing deleted. It is a so called detached object. To use it within the session for example deleting it you need to first associate it with the currently opened session. There are several ways to achive this:
ISession.Get()
orISession.Load()
.session
withISession.Lock()
Otherwise you'll probably get
StaleStateException
s and the like.Remeber to read up on the NHibernate documentation