我在我的应用程序中使用NHibernate和Repository模式。但不想使用UnitofWork模式。
我的应用中有两种类型的表单。收集/选择器表单和实体表单。
但是当一个表单是另一个表单中的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);
}
}
我声明我的个人存储库是这样的:
public class FacultyRepository : Repository<Faculty>
{
}
public class DepartmentRepository : Repository<Department>
{
}
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;
}
}
}
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();
}
}
答案 0 :(得分:2)
我通过ISession static
中的SessionFactory
解决了这个问题,而不是为每个存储库返回一个开放ISession
,我只返回一个static
ISession