NHibernate ISession 生命周期;什么时候可以在每个存储库方法中创建/处置?

发布于 2024-10-15 17:28:49 字数 1771 浏览 1 评论 0原文

我正在使用单层单用户应用程序和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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夏日落 2024-10-22 17:28:49

当您引用延迟加载字段时,会话必须打开,因此,如果您依赖存储库外部的延迟加载,则需要在更高的位置管理会话生命周期。

如果不使用延迟加载,还存在是否需要在一个事务中支持多个操作的问题。例如,如果您一次性删除一个产品和一些其他数据,您希望在同一会话的一个事务中发生这种情况(否则您可能会删除该产品,让某些代码抛出一些异常,并且永远不会删除其他数据)数据,最终可能会出现孤立记录或数据库中的损坏状态)。

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).

如痴如狂 2024-10-22 17:28:49

我认为你应该为每个线程使用 UnitOfWork 模式。
在线程开始时创建ISession并用它初始化UnitOfWork。存储库将 UnitOfWork 与该信号 ISession 结合使用。在线程执行结束时提交更改,如果与其他线程发生冲突则回滚。

I think you should use UnitOfWork pattern per thread.
On thread start create ISession and initialize UnitOfWork with it. Repositories use UnitOfWork with that signle ISession. At the end of thread execution commit the changes or rollback if there was conflict with other threads.

小矜持 2024-10-22 17:28:49

产品被删除时不与任何会话关联。它是一个所谓的分离对象。要在会话中使用它(例如删除它),您需要首先将其与当前打开的会话关联。有多种方法可以实现此目的:

  1. 保持会话开放。如果在加载产品时和删除产品时打开相同的会话,则它将正常工作。
  2. 重新加载对象,但使用 ISession.Get()ISession.Load()
  3. 使用 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:

  1. Keep the session open. If the same session is opened when the Product is loaded as when it is deleted, it will work fine.
  2. Reload the object, but using ISession.Get() or ISession.Load().
  3. Re-attach the object to the newly opened session session with ISession.Lock()

Otherwise you'll probably get StaleStateExceptions and the like.

Remeber to read up on the NHibernate documentation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文