【问题标题】:What is a good way to setup CRUD methods and SessionFactory in Nhibernate?在 Nhibernate 中设置 CRUD 方法和 SessionFactory 的好方法是什么?
【发布时间】:2011-04-03 01:20:48
【问题描述】:

我目前有一个创建会话工厂的 NHibernateHelper 类。我不断收到错误提示“会话已关闭!”。我会以错误的方式解决这个问题吗?当我调用 Add(User user) 之后调用的 Add(Login login) 时发生错误

public class NHibernateHelper
{
    private static ISessionFactory _sessionFactory;

    private static ISessionFactory SessionFactory
    {
        get
        {
            if (_sessionFactory == null)
            {
                var configuration = new Configuration();
                configuration.Configure();
                configuration.AddAssembly("System.Core");
                _sessionFactory = configuration.BuildSessionFactory();
            }
            return _sessionFactory;
        }
    }

    public static ISession OpenSession()
    {
        return SessionFactory.OpenSession();
    }
}

这是我的存储库:

internal class UserRepository : IUserRepository
{
    private ISession _db = NHibernateHelper.OpenSession();

    public void Add(User user)
        {
            using (_db)
            {
                using (ITransaction transaction = _db.BeginTransaction())
                {
                    IEnumerable<UserRole> userRoles = user.UserRoles;
                    user.UserRoles = null;
                    _db.Save(user);
                    foreach (UserRole userRole in userRoles)
                    {
                        userRole.UserID = user.UserID;
                        _db.Save(userRole);
                    }
                    transaction.Commit();
                }
            }
        }



        public void Add(Login login)
        {
            using (_db)
            {
                using (ITransaction transaction = _db.BeginTransaction())
                {
                    _db.Save(login);
                    transaction.Commit();
                }
            }

        }
}

【问题讨论】:

    标签: c# nhibernate sessionfactory


    【解决方案1】:

    这是因为您正在调用 using(_db),它会在块结束时关闭会话。

    而不是让变量 _db 只是为每个操作调用 OpenSession

        public void Add(User user)
        {
            using (ISession session = NHibernateHelper.OpenSession())
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    IEnumerable<UserRole> userRoles = user.UserRoles;
                    user.UserRoles = null;
                    session.Save(user);
                    foreach (UserRole userRole in userRoles)
                    {
                        userRole.UserID = user.UserID;
                        session.Save(userRole);
                    }
                    transaction.Commit();
                }
    
            }
        }
    

    更新:

       public void Add(Login login)
       {
            using (ISession session = NHibernateHelper.OpenSession())
            {
                 Add(login, session);
            }
       }
    
       public void Add(Login login, ISession session)
       {
            //no longer need to create a session here - it is passed in
            //using (ISession session = NHibernateHelper.OpenSession()) 
    
            ...Add using the session
       }
    

    这是工厂的创建是昂贵的,所以你的助手是一个好用的东西。打开会话是一个便宜的操作,所以不需要像这样的共享会话。

    这是另一个 SO 问题的链接,该问题展示了如何使您的工厂助手线程安全:

    Ensure NHibernate SessionFactory is only created once

    【讨论】:

    • 通过像上面这样使用它不会为每个 crud 操作创建一个工厂实例吗?
    • 不,工厂是静态单例。将为每个操作创建 ISession。由于 _db 被关闭,请参阅我的编辑。 - 我的答案的第一行。
    • 另外,你可以通过在以下行下断点来测试是否创建了新工厂: if (_sessionFactory == null)
    • 每组相关活动只需要一个事务。如果您正在执行多项更改,请在调用 OpenSession 之后立即创建转换,就像您在问题的第一个代码块中所做的那样,然后像您所做的那样在右大括号之前提交它。
    • 当我有机会时(即当我回到家时),我会整理一个示例应用程序。给我发一封电子邮件,我们可以建立一个离线对话,也许稍后将结果发布在这里作为新的答案。
    猜你喜欢
    • 1970-01-01
    • 2020-07-26
    • 2015-02-19
    • 2011-04-05
    • 1970-01-01
    • 2018-10-11
    • 2012-01-29
    • 2011-09-17
    • 1970-01-01
    相关资源
    最近更新 更多