I'm new to NHibernate and trying to use it in ASP.NET WEB API. Firstly I used it successfully with one table named "Category" which the controller class is as follow:
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using TestMVCProject.Web.Api.HttpFetchers;
using TestMVCProject.Web.Api.Models;
using TestMVCProject.Web.Api.TypeMappers;
using TestMVCProject.Web.Common;
//using TestMVCProject.Web.Common.Security;
using NHibernate;
namespace TestMVCProject.Web.Api.Controllers
{
[LoggingNHibernateSession]
public class CategoryController : ApiController
{
private readonly ISession _session;
private readonly ICategoryMapper _categoryMapper;
private readonly IHttpCategoryFetcher _categoryFetcher;
public CategoryController(
ISession session,
ICategoryMapper categoryMapper,
IHttpCategoryFetcher categoryFetcher)
{
_session = session;
_categoryMapper = categoryMapper;
_categoryFetcher = categoryFetcher;
}
public IEnumerable<Category> Get()
{
return _session
.QueryOver<Data.Model.Category>()
.List()
.Select(_categoryMapper.CreateCategory)
.ToList();
}
public Category Get(long id)
{
var category = _categoryFetcher.GetCategory(id);
return _categoryMapper.CreateCategory(category);
}
public HttpResponseMessage Post(HttpRequestMessage request, Category category)
{
var modelCategory = new Data.Model.Category
{
Description = category.Description,
CategoryName = category.CategoryName
};
_session.Save(modelCategory);
var newCategory = _categoryMapper.CreateCategory(modelCategory);
//var href = newCategory.Links.First(x => x.Rel == "self").Href;
var response = request.CreateResponse(HttpStatusCode.Created, newCategory);
//response.Headers.Add("Location", href);
return response;
}
public HttpResponseMessage Delete()
{
var categories = _session.QueryOver<Data.Model.Category>().List();
foreach (var category in categories)
{
_session.Delete(category);
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
public HttpResponseMessage Delete(long id)
{
var category = _session.Get<Data.Model.Category>(id);
if (category != null)
{
_session.Delete(category);
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
public Category Put(long id, Category category)
{
var modelCateogry = _categoryFetcher.GetCategory(id);
modelCateogry.CategoryName = category.CategoryName;
modelCateogry.Description = category.Description;
_session.SaveOrUpdate(modelCateogry);
return _categoryMapper.CreateCategory(modelCateogry);
}
}
}
But when I add The "Product" table which has a foreign key of the Category table, the product controller doesn't work and throws below exception:
No session bound to the current context
ProductController
class is as follow:
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using TestMVCProject.Web.Api.HttpFetchers;
using TestMVCProject.Web.Api.Models;
using TestMVCProject.Web.Api.TypeMappers;
using TestMVCProject.Web.Common;
//using TestMVCProject.Web.Common.Security;
using NHibernate;
namespace TestMVCProject.Web.Api.Controllers
{
[LoggingNHibernateSession]
public class ProductController : ApiController
{
private readonly ISession _session;
private readonly IProductMapper _productMapper;
private readonly IHttpProductFetcher _productFetcher;
public ProductController(
ISession session,
IProductMapper productMapper,
IHttpProductFetcher productFetcher)
{
_session = session;
_productMapper = productMapper;
_productFetcher = productFetcher;
}
public IEnumerable<Product> Get()
{
return _session
.QueryOver<Data.Model.Product>()
.List()
.Select(_productMapper.CreateProduct)
.ToList();
}
public Product Get(long id)
{
var product = _productFetcher.GetProduct(id);
return _productMapper.CreateProduct(product);
}
public HttpResponseMessage Post(HttpRequestMessage request, Product product)
{
var modelProduct = new Data.Model.Product
{
Description = product.Description,
ProductName = product.ProductName
};
_session.Save(modelProduct);
var newProduct = _productMapper.CreateProduct(modelProduct);
//var href = newproduct.Links.First(x => x.Rel == "self").Href;
var response = request.CreateResponse(HttpStatusCode.Created, newProduct);
//response.Headers.Add("Location", href);
return response;
}
public HttpResponseMessage Delete()
{
var categories = _session.QueryOver<Data.Model.Product>().List();
foreach (var product in categories)
{
_session.Delete(product);
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
public HttpResponseMessage Delete(long id)
{
var product = _session.Get<Data.Model.Product>(id);
if (product != null)
{
_session.Delete(product);
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
public Product Put(long id, Product product)
{
var modelProduct = _productFetcher.GetProduct(id);
modelProduct.ProductName = product.ProductName;
modelProduct.Description = product.Description;
_session.SaveOrUpdate(modelProduct);
return _productMapper.CreateProduct(modelProduct);
}
}
}
and the mapping class for Product table:
using TestMVCProject.Data.Model;
using FluentNHibernate.Mapping;
namespace TestMVCProject.Data.SqlServer.Mapping
{
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Id(x => x.ProductId);
Map(x => x.ProductName).Not.Nullable();
Map(x => x.Description).Nullable();
Map(x => x.CreateDate).Not.Nullable();
Map(x => x.Price).Not.Nullable();
References<Category>(x => x.CategoryId).Not.Nullable();
}
}
}
What is wrong?
Your snippets are missing the way, how the
ISessionFactory
is created and howISession
is passed into your controllers... You should follow this really comprehensive story (by Piotr Walat):NHibernate session management in ASP.NET Web API
Where you can see that we, can use 2.3. Contextual Sessions:
The configuration
In the article you can check that we need at the app start initialize factory (just an extract):
Next we should create some AOP filter (just an extract):
For more details check the source mentioned above