nhibernate を使用して mySQL db とやり取りする非常に単純な CRUD asp.net-mvc サイトがあります。UnitOfWork および Repository パターンを使用しています。MVC 4 と最新の nhibernate および mySQL バージョン (nuget 経由) にアップグレードした後、更新と削除が機能しなくなるという奇妙な問題が突然発生します。
動作を停止したコントローラーの削除コードの例を次に示します。
public ActionResult Delete(int id)
{
MyEvent c = _eventRepository.FindBy(id);
_unitOfWork.Begin();
_eventRepository.Delete(c);
_unitOfWork.End();
return RedirectToAction("Index");
}
UnitOfWork コードは次のようになります。
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession();
Session.FlushMode = FlushMode.Auto;
}
public void End()
{
Commit();
if (Session.IsOpen)
{
Session.Close();
}
}
public void Commit()
{
if (!_transaction.IsActive)
{
throw new InvalidOperationException("No active transation");
}
_transaction.Commit();
}
public void Begin()
{
_transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
正常に機能する新しい項目を追加してテストしました (DB テーブルに新しい行が表示されます) が、更新または削除をテストすると、コードは正常に実行されます (コードで例外は発生しません)。更新を実行すると更新され、削除コードを実行してもレコードは削除されません。
要約すると、mySQL db からのデータの読み取りは正常に機能し、追加は正常に機能しますが、更新と削除はすべてのテーブルで機能しなくなりました (以前は機能していました)。Toad for MySQL を使用して通常の SQL を実行するテストを行ったところ、正常に動作しました (コードで接続に使用しているのと同じログイン資格情報を使用)。
もう少しデバッグを支援するために、nhibernate プロファイラーを起動しました。これは、削除または更新エントリに表示されるものです。
そして、これは私が通常の読み取りページを読み込んでいるのを見るものです:
それが問題の説明に役立つかどうかはわかりませんが、スクリーンショットを追加しても害はないと考えました.
何が起こっているのかについての提案。これは資格の問題である可能性があります (ソフトウェア ライブラリのバグではありませんか?)。繰り返しますが、前述のように、このコードは以前は確実に機能していました。
これが私のNinject Iocコードです:
string connectionString = ConfigurationManager.ConnectionStrings["LocalMySqlServer"].ConnectionString;
var helper = new NHibernateHelper(connectionString);
Bind<ISessionFactory>().ToConstant(helper.SessionFactory)
.InSingletonScope();
Bind<IUnitOfWork>().To<UnitOfWork>();
var sessionProvider = new SessionProvider();
Bind<ISession>().ToProvider(sessionProvider);
var unitOfWork = new UnitOfWork(helper.SessionFactory);
Bind(typeof(IIntKeyedRepository<>)).To(typeof(Repository<>));
}
ここに私のunitofwork.csコードがあります:
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private ITransaction _transaction;
public ISession Session { get; private set; }
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession();
Session.FlushMode = FlushMode.Auto;
}
public void End()
{
Commit();
if (Session.IsOpen)
{
Session.Close();
}
}
public void Begin()
{
_transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public void Dispose()
{
if (Session.IsOpen)
{
Session.Close();
}
}
public void Commit()
{
if (!_transaction.IsActive)
{
throw new InvalidOperationException("No active transation");
}
_transaction.Commit();
}
public void Rollback()
{
if (_transaction.IsActive)
{
_transaction.Rollback();
}
}
}
ここに私のリポジトリコードがあります:
public class Repository<T> : IIntKeyedRepository<T> where T : class
{
private readonly ISession _session;
private ITransaction _trans;
public T FindBy(int id)
{
return _session.Get<T>(id);
}
public Repository(ISession session)
{
_session = session;
}
public bool Add(T entity)
{
_session.Save(entity);
return true;
}
public bool Add(IEnumerable<T> items)
{
foreach (T item in items)
{
_session.Save(item);
}
return true;
}
public bool Update(T entity)
{
_session.Update(entity);
return true;
}
public bool Delete(T entity)
{
_session.Delete(entity);
return true;
}
public bool Delete(IEnumerable<T> entities)
{
foreach (T entity in entities)
{
_session.Delete(entity);
}
return true;
}
#endregion
#region IIntKeyedRepository<T> Members
public T FindBy(int id)
{
return _session.Get<T>(id);
}
#endregion
#region IReadOnlyRepository<T> Members
public IQueryable<T> All()
{
return _session.Query<T>();
}
public T FindBy(Expression<Func<T, bool>> expression)
{
return FilterBy(expression).Single();
}
public IQueryable<T> FilterBy(Expression<Func<T, bool>> expression)
{
return All().Where(expression).AsQueryable();
}
}