Проблема шаблона репозитория NHibernate - PullRequest
2 голосов
/ 08 ноября 2010

Я использую шаблоны NHibernate и Repository в своем приложении.Но я не хочу использовать шаблон UnitofWork.

В моем приложении есть два типа форм.Формы сбора / выбора и формы сущностей.

Dept Collection Form

Dept Entity Form

Но проблема возникает, когда форма вызывается ShowDialog () из другой формы.

Несмотря на то, что я выполняю любую операцию, связанную с базой данных, NHibernate дает мне сообщение об ошибке «другой объект с таким же значением идентификатора уже был связан с сеансом: XYZ».Это вызвано задержкой вызова метода Dispose из CLR, и, насколько я понимаю, другая часть моей проблемы связана с управлением сеансом.

Как изменить коды репозитория для решения моей проблемы?

Помните, я не хочу показывать отдельные функции, подобные 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);
        }

A Сохранение работает следующим образом,

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 Ответ

2 голосов
/ 13 ноября 2010

ОК, ребята! Прошло много времени с тех пор, как я опубликовал свой вопрос, и никто не склонен отвечать на него.

Я решил, сделав ISession static в SessionFactory и вместо возврата Open ISession для каждого репозитория, я возвращаю только один static ISession.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...