3

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

1 に答える 1

1

このコードには、1 つのセッションの範囲内にある Find 関数と Delete 関数の呼び出しが含まれています。私が思うに、質問からのコードの問題は、異なるものを使用していることです。

public T RemoveById(int id)
{
    _transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
    T res=_session.Get<T>(id);
    _session.Delete(entity);
    _transaction.Commit(); 
}

(アクションからの呼び出し:)

RemoveById<MyEvent>(id)
于 2012-09-29T12:31:51.597 に答える