开发者

NHibernate Repository pattern problem

开发者 https://www.devze.com 2023-01-23 18:42 出处:网络
I am using NHibernate and Repository patterns in my application. But not want to use UnitofWork pattern.

I am using NHibernate and Repository patterns in my application. But not want to use UnitofWork pattern.

There are two types of forms in my app. Collection/Picker forms and Entity forms.

NHibernate Repository pattern problem

NHibernate Repository pattern problem

But the problem occurs when a form is ShowDialog()ged from within another form.

Whwn I am doing any database related operation, NHibernate is giving me "a different object with the same identifier value was already associated with the session: XYZ" error. This is caused due to the delayed call of Dispose method by CLR and another part of my problem is in the Session management as far as I guess.

How can I change my repository codes to solve my problem?

Remember, I don't want to expose separate BeginTransaction(), CommitTransaction() like functions in my Repository. These things should be embedded within every Method {SaveOrUpdate(), Save(), Delete, Load(), etc.} as I have already done.

Please tell me how can I get things going with minor changes?

I am doing my things like this:

A picker form works like this,

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);
        }

A Save works like this,

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);
        }
    }

I declare my individual repositories like this:

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.GetOp开发者_如何学运维enSession();
        }

        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();
        }
    }


OK guys! It has been long since I posted my question and nobody tends to answer it.

I solved it by making ISession static in the SessionFactory and instead of returning a Open ISession for each Repository, I am returning only one static ISession.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号