Why would my asp.net-mvc site using nhibernate sim

2019-07-04 00:18发布

问题:

I have a very simple CRUD asp.net-mvc site that uses nhibernate to interface with a mySQL db. I am using the UnitOfWork and Repository patterns. After upgrading to MVC 4 and the latest nhibernate and mySQL versions (via nuget) I am suddenly seeing a weird issue where updates and deletes have stopped working.

Here is an example Delete code in my controller that stopped working:

    public ActionResult Delete(int id)
    {
        MyEvent c = _eventRepository.FindBy(id);

        _unitOfWork.Begin();
        _eventRepository.Delete(c);
        _unitOfWork.End();

        return RedirectToAction("Index");
    }

where the UnitOfWork code looks like this:

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

I tested adding a new item that worked fine (new row shows up in DB table) but when I test either Updates or Deletes, the code runs fine (I don't get any exceptions in the code) but the fields aren't being updated when i do an Update and the record isn't deleted when I run the delete code.

So to recap, reading data from mySQL db works fine, doing adds works fine but updates and deletes have stopped working for all tables (which did work before). I did a test doing regular SQL using Toad for MySQL and that worked fine (using the same login credentials that i am using to connect in my code)

To help debug a bit more, I started up nhibernate profiler and this is what i see for a delete or update entry:

and this is what i see loading a regular read page:

not sure if that is helpful in explaining the issue but i figured it couldn't hurt to add the screenshots.

Any suggestions on what could be happening. Could this be an entitlement issue (versus some software library bug?). Again, as mentioned above this code previously definitely worked.

Here is my Ninject Ioc Code:

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

and here is my unitofwork.cs code:

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

and here is my repository code:

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

回答1:

This code includes Find and Delete functions calls in scope of a single session. As I think, problem in code from question is using different ones.

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

(call from action:)

RemoveById<MyEvent>(id)