views:

45

answers:

2

Hi everybody,

I am developing with NHibernate for the first time in conjunction with ASP.NET MVC and StructureMap. The CodeCampServer serves as a great example for me. I really like the different concepts which were implemented there and I can learn a lot from it.

In my controllers I use Constructur Dependency Injection to get an instance of the specific repository needed.

My problem is: If I change an attribute of the customer the customer's data is not updated in the database, although Commit() is called on the transaction object (by a HttpModule).

public class AccountsController : Controller
{
    private readonly ICustomerRepository repository;

    public AccountsController(ICustomerRepository repository)
    {
        this.repository = repository;
    }

    public ActionResult Save(Customer customer)
    {
        Customer customerToUpdate = repository
            .GetById(customer.Id);

        customerToUpdate.GivenName = "test"; //<-- customer does not get updated in database
        return View();      
    }
}

On the other hand this is working:

public class AccountsController : Controller
{
    [LoadCurrentCustomer]
    public ActionResult Save(Customer customer)
    {
        customer.GivenName = "test"; //<-- Customer gets updated
        return View();              
    }
}

public class LoadCurrentCustomer : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        const string parameterName = "Customer";

        if (filterContext.ActionParameters.ContainsKey(parameterName))
        {
            if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            {                    
                Customer CurrentCustomer = DependencyResolverFactory
                    .GetDefault()
                    .Resolve<IUserSession>()
                    .GetCurrentUser();

                filterContext.ActionParameters[parameterName] = CurrentCustomer;
            }
        }

        base.OnActionExecuting(filterContext);
    }
}

public class UserSession : IUserSession
{
    private readonly ICustomerRepository repository;

    public UserSession(ICustomerRepository customerRepository)
    {
        repository = customerRepository;
    }

    public Customer GetCurrentUser()
    {
        var identity = HttpContext.Current.User.Identity;

        if (!identity.IsAuthenticated)
        {
            return null;
        }

        Customer customer = repository.GetByEmailAddress(identity.Name);
        return customer;
    }
}

I also tried to call update on the repository like the following code shows. But this leads to an NHibernateException which says "Illegal attempt to associate a collection with two open sessions". Actually there is only one.

public ActionResult Save(Customer customer)
{
    Customer customerToUpdate = repository
        .GetById(customer.Id);

    customer.GivenName = "test";
    repository.Update(customerToUpdate);

    return View();  
}

Does somebody have an idea why the customer is not updated in the first example but is updated in the second example? Why does NHibernate say that there are two open sessions?

A: 

try calling repository.Flush()

Al W
A: 

Finally I found the problem. When I was getting the customer by it's id I always opened a new session, instead of using the session within the request scope.

However, thanks a lot for your help!