NHibernate存储库模式问题

时间:2010-11-08 04:17:20

标签: nhibernate repository-pattern session-management

我在我的应用程序中使用NHibernate和Repository模式。但不想使用UnitofWork模式。

我的应用中有两种类型的表单。收集/选择器表单和实体表单。

Dept Collection Form

Dept Entity Form

但是当一个表单是另一个表单中的ShowDialog()ged时会出现问题。

当我正在做任何与数据库相关的操作时,NHibernate给了我“具有相同标识符值的不同对象已经与会话关联:XYZ”错误。这是由于CLR对Dispose方法的延迟调用造成的,而我的问题的另一部分就是我认为的会话管理。

如何更改我的存储库代码以解决我的问题?

请记住,我不希望在我的存储库中公开单独的BeginTransaction(),CommitTransaction()。这些东西应该嵌入到我已经完成的每个方法{SaveOrUpdate(),Save(),Delete,Load()等}中。

请告诉我如何通过微小改动让事情顺利进行?

我正在做这样的事情:

选择器表单的工作原理如下,

private void btnPick_Click(object sender, EventArgs e)
        {
            CourseCollectionForm f = new CourseCollectionForm();
            f.FormViewMode = FormViewMode.MultiplePicker;
            f.ShowDialog();

            int totalCredits = 0;
            int totalHours = 0;

            FillDataGridViewWithCourses(f.PickedCourseCollection, ref totalCredits, ref totalHours);

            FillTotal(totalCredits, totalHours);
        }

保存就像这样,

public partial class DepartmentEntityForm : Form
    {
        private DepartmentRepository _deptRepository = null;
        private Department _currentDepartment = null;
        private FormViewMode _currentMode = FormViewMode.None;

        public DepartmentEntityForm(Department dept, FormViewMode mode)
        {
            InitializeComponent();

            _deptRepository = new DepartmentRepository();

            _currentDepartment = dept;
            _currentMode = mode;

            if(mode == FormViewMode.Edit)
            {
                MapObjectToControls();
            }
        }

        private void SaveButton_Click(object sender, EventArgs e)
        {
            Department newDept;

            if (mode == FormViewMode.AddNew)
            {
                newDept = new Department();
            }
            else if(mode == FormViewMode.Edit)
            {
                newDept = _currentDepartment;
            }
            //.............
            //.............

            _deptRepository.SaveOrUpdate(newDept);
        }
    }

我声明我的个人存储库是这样的:

FacultyRepository.cs

public class FacultyRepository : Repository<Faculty>
    {
    }

DepartmentRepository.cs

public class DepartmentRepository : Repository<Department>
    {
    }

Repository.cs

public class Repository<T> : IRepository<T>
    {
        ISession _session;

        public Repository() 
        {
            _session = SessionFactory.GetOpenSession();
        }

        public T Get(object id)
        {
            T obj = default(T);

            try
            {
                if (!_session.Transaction.IsActive)
                {
                    _session.BeginTransaction();
                    obj = (T)_session.Get<T>(id);
                    _session.Transaction.Commit();
                    _session.Flush();
                }
                else
                {
                    throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
                }
            }
            catch (Exception ex)
            {
                _session.Transaction.Rollback();
                _session.Clear();

                throw ex;
            }

            return obj;
        }

        public IEnumerable<T> Get(string fieldName, object fieldValue)
        {
            IEnumerable<T> list = null;

            try
            {
                if (!_session.Transaction.IsActive)
                {
                    _session.BeginTransaction();
                    list = (IEnumerable<T>)_session.CreateCriteria(typeof(T))
                        .Add(new NHibernate.Expression.EqExpression(fieldName, fieldValue))
                        .List<T>();

                    _session.Transaction.Commit();
                    _session.Flush();
                }
                else
                {
                    throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
                }
            }
            catch (Exception ex)
            {
                _session.Transaction.Rollback();
                _session.Clear();

                throw ex;
            }

            return list;
        }

        public IEnumerable<T> Get()
        {
            IEnumerable<T> list = null;

            try
            {
                if (!_session.Transaction.IsActive)
                {
                    _session.BeginTransaction();
                    list = (IEnumerable<T>)_session.CreateCriteria(typeof(T)).List<T>();
                    _session.Transaction.Commit();
                    _session.Flush();
                }
                else
                {
                    throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
                }
            }
            catch (Exception ex)
            {
                _session.Transaction.Rollback();
                _session.Clear();

                throw ex;
            }

            return list;
        }

        public void SaveOrUpdate(T obj)
        {
            try
            {
                if (!_session.Transaction.IsActive)
                {
                    _session.BeginTransaction();
                    _session.SaveOrUpdateCopy(obj);
                    _session.Transaction.Commit();
                    _session.Flush();
                }
                else
                {
                    throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
                }
            }
            catch (Exception ex)
            {
                _session.Transaction.Rollback();
                _session.Clear();

                throw ex;
            }
        }

        public void SaveOrUpdate(IEnumerable<T> objs)
        {
            try
            {
                if (!_session.Transaction.IsActive)
                {
                    _session.BeginTransaction();

                    foreach (T obj in objs)
                    {
                        _session.SaveOrUpdate(obj);
                    }

                    _session.Transaction.Commit();
                    _session.Flush();
                }
                else
                {
                    throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
                }
            }
            catch (Exception ex)
            {
                _session.Transaction.Rollback();
                _session.Clear();

                throw ex;
            }
        }

        public void Delete(T obj)
        {
            try
            {
                if (!_session.Transaction.IsActive)
                {
                    _session.BeginTransaction();
                    _session.Delete(obj);
                    _session.Transaction.Commit();
                    _session.Flush();
                }
                else
                {
                    throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
                }
            }
            catch (Exception ex)
            {
                _session.Transaction.Rollback();                
                _session.Clear();

                throw ex;
            }
        }

        public void Delete(IEnumerable<T> objs)
        {
            try
            {
                if (!_session.Transaction.IsActive)
                {
                    _session.BeginTransaction();

                    foreach (T obj in objs)
                    {
                        _session.Delete(obj);
                    }

                    _session.Transaction.Commit();
                    _session.Flush();
                }
                else
                {
                    throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
                }
            }
            catch (Exception ex)
            {
                _session.Transaction.Rollback();
                _session.Clear();

                throw ex;
            }
        }

        public void DeleteAll()
        {
            try
            {
                if (!_session.Transaction.IsActive)
                {
                    _session.BeginTransaction();

                    DetachedCriteria criterion = DetachedCriteria.For<T>();
                    IList<T> list = criterion.GetExecutableCriteria(_session).List<T>();

                    foreach (T item in list)
                    {
                        _session.Delete(item);
                    }

                    _session.Transaction.Commit();
                    _session.Flush();
                }
                else
                {
                    throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
                }
            }
            catch (Exception ex)
            {
                _session.Transaction.Rollback();

                throw ex;
            }
        }

        public void Dispose()
        {
            if (_session != null)
            {
                _session.Clear();
                _session.Close();
                _session = null;
            }
        }
    }

SessionFactory.cs

public class SessionFactory
    {
        private static ISessionFactory _sessionFactory = null;
        private SessionFactory(){}

        static SessionFactory()
        {
            if (_sessionFactory == null)
            {
                Configuration configuration = new Configuration();
                configuration.Configure();
                _sessionFactory = configuration.BuildSessionFactory();
            }
        }

        public static ISession GetOpenSession()
        {
            return _sessionFactory.OpenSession();
        }
    }

1 个答案:

答案 0 :(得分:2)

好的伙计们!我发布问题已经很久没有人倾向于回答它了。

我通过ISession static中的SessionFactory解决了这个问题,而不是为每个存储库返回一个开放ISession,我只返回一个static ISession