views:

215

answers:

1

I have a very strange problem: NHibernate crashes when being called from a web user control.

I am working on a ASP.Net (2.0) web page which uses NHibernate to access a database.

And I have a simple factory class to access a column CurrentStepNumber in the table ProjectInfo:

public class ProjectEntity
{
    private int? _currentStepNumber;
    public virtual int? CurrentStepNumber
    {
        get { return _currentStepNumber; }
        set { _currentStepNumber = value; }
    }

    public static ProjectWizardEntity GetById(int id, bool shouldLock) 
    {
        return RepositoryFactory.ProjectWizardRepository.GetById(id, shouldLock);
    }

    public static ProjectWizardEntity GetById(int id) 
    {
        return GetById(id, false);
    }

    public virtual void Save() 
    {
        RepositoryFactory.ProjectWizardRepository.Save(this);
    }

    public virtual void SaveOrUpdate() 
    {   
        RepositoryFactory.ProjectWizardRepository.SaveOrUpdate(this);
    }
}

This class is accessed via a proxy class, so that everytime a new value is assigned it is flushed to the database:

public class DBHelper
{
ProjectEntity _projectEntity;
ProjectEntity GetProjectEntity()
{
    if (_projectEntity == null)
        _projectEntity = //get or create a new one;

    return _projectEntity ;
}

public int? CurrentStepNumber
{
    get
    {
        return (CurrentProjectId > 0) ? CurrentProjectWizardEntity.CurrentStepNumber : 0;
    }
    set
    {
        if (CurrentProjectId > 0)
        {

            CurrentProjectWizardEntity.CurrentStepNumber = value;
            CurrentProjectWizardEntity.SaveOrUpdate();
        }
    }
}
}

Now the problem:

  1. When I access CurrentStepNumber from the test.aspx page, everything works perfectly
  2. When I read this field from the web user control (test.ascx) which is used on test.aspx page it is still OK
  3. However when I try to assign a value to CurrentStepNumber in the code behind the control (test.ascx) I always get an exception:

NHibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

Actually SaveOrUpdate method of the NHibernate Repository throws the exception.

I could not figure out what could be the problem here, so any help will be appreciated.

A: 

I think that You have a session management problem here. How is RepositoryFactory.ProjectWizardRepository.GetById creating and possibly disposing the NHibernate session? Does it create and then close a session?

It seems that DBHelper.GetProjectEntity() is creating or loading a ProjectEntity. Later, when CurrentStepNumber's setter i called, You insert or update the object to the database.

The problem is that when DBHelper.GetProjectEntity() is loading an existing object and later closing the session after it has been loaded but keep the object around, we are entering deep water. When the object is later updated, You set a new value for CurrentStepNumber and send the object to NHibernate to save. The problem here is that the object is not associated with the new session that is created and closed during saving. Nhibernate then gets confused since a new object is discovered that is not loaded from current session but it has an id of an existing object.

For a solution, Google for "NHibernate asp.net session management" and You will get a number of good hits about how to use the ASP.NET request cycle as a unit of work.

Andreas Paulsson