首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Web中的NHibernate :没有与当前上下文绑定的会话

Web中的NHibernate :没有与当前上下文绑定的会话
EN

Stack Overflow用户
提问于 2015-03-28 04:36:58
回答 2查看 3.5K关注 0票数 3

我对NHibernate很陌生,并试图在ASP.NET WEB中使用它。首先,我成功地使用了一个名为“类别”的表,控制器类如下所示:

代码语言:javascript
复制
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);
        }
    }
}

但是,当我添加带有类别表外键的" product“表时,产品控制器无法工作,并抛出异常:

没有绑定到当前上下文的会话。

ProductController类如下所示:

代码语言:javascript
复制
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);
        }
    }
}

和Product的映射类:

代码语言:javascript
复制
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();               
        }
    }
}

怎么啦?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-28 06:54:56

您的代码片段错过了如何创建ISessionFactory,以及如何将ISession传递给控制器.您应该遵循这个非常全面的故事( Piotr Walat__)

NHibernate Web中的ASP.NET会话管理

你可以看到我们,可以使用2.3。语境会话

NHibernate.Context.WebSessionContext -将当前会话存储在HttpContext中。您负责用类ISession的静态方法绑定和取消绑定一个CurrentSessionContext实例。

配置

代码语言:javascript
复制
<session-factory>
    ..
    <property name="current_session_context_class">web</property>
</session-factory>

在本文中,您可以检查我们需要在应用程序开始初始化工厂(只是一个摘录)

代码语言:javascript
复制
public class WebApiApplication : System.Web.HttpApplication  
{
    private void InitializeSessionFactory() { ... }

    protected void Application_Start()
    {
        InitializeSessionFactory();
    ...

接下来,我们应该创建一些AOP过滤器(只是一个摘录)

代码语言:javascript
复制
public class NhSessionManagementAttribute : ActionFilterAttribute  
{
    ...
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        // init session
        var session = SessionFactory.OpenSession();
        ...

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        // close session
        ...
        session = CurrentSessionContext.Unbind(SessionFactory);
    }

有关更多详细信息,请查看上文所述来源

票数 4
EN

Stack Overflow用户

发布于 2015-03-30 03:46:34

将会话传递给控制器工厂的构造函数的方法似乎不起作用,有几种方法可以做到这一点

1.使用依赖注入

如果使用依赖项注入框架,则必须配置控制器,以便根据请求构造控制器,它应该如下所示(我已经为Ninject使用了代码)

步骤1-设置注入会话

代码语言:javascript
复制
public class DIModule : NinjectModule
{
    public override void Load()
    {
    this.Bind<ISessionFactory>()... bind to the session factory
        this.Bind<ISession>().ToMethod(ctx => ctx.Kernel.Get<ISessionFactory>().OpenSession())
            .InRequestScope();
    }

    private ISession CreateSessionProxy(IContext ctx)
    {
        var session = (ISession)this.proxyGenerator.CreateInterfaceProxyWithoutTarget(typeof(ISession), new[] { typeof(ISessionImplementor) }, ctx.Kernel.Get<SessionInterceptor>());
        return session;
    }
}

步骤2-创建控制器工厂,以便在解析时注入会话。

代码语言:javascript
复制
public class NinjectControllerFactory : DefaultControllerFactory, IDependencyResolver
    {
        private IDependencyResolver _defaultResolver;

        public NinjectControllerFactory(IDependencyResolver defaultResolver)
        {
            _defaultResolver = defaultResolver;
        }

        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            return controllerType == null
                   ? null
                   : (IController)DependencyKernel.Kernel.Get(controllerType);
        }

        public IDependencyScope BeginScope()
        {
            return this;
        }

        public object GetService(Type serviceType)
        {
            try
            {
                return DependencyKernel.Kernel.Get(serviceType);
            }
            catch (Exception)
            {
                return GetService(serviceType);
            }
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            try
            {
                object item = DependencyKernel.Kernel.Get(serviceType);
                return new List<object>() {item};
            }
            catch (Exception)
            {
                return GetServices(serviceType);
            }
        }

        public void Dispose()
        {
        }
    }

步骤3-注册控制器工厂

代码语言:javascript
复制
public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {

            var factory = new NinjectControllerFactory(GlobalConfiguration.Configuration.DependencyResolver);
            ControllerBuilder.Current.SetControllerFactory(factory);
            GlobalConfiguration.Configuration.DependencyResolver = factory;
        }
    }

现在会发生的是,当您的控制器被创建时,它将为每个请求注入一个新的NH会话。

2.使用过滤器

这要简单得多,但您可能需要稍微更改控制器才能工作,

步骤1-为工厂设置正确的会话上下文

代码语言:javascript
复制
_sessionFactory = CreateConfiguration()
                .ExposeConfiguration(c => c.SetProperty("current_session_context_class","web"))
                .BuildSessionFactory();

步骤2-创建过滤器

代码语言:javascript
复制
public class SessionPerRequestAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var session = SessionFactory.OpenSession();
            NHibernate.Context.CurrentSessionContext.Bind(session);
            base.OnActionExecuting(actionContext);
        }

        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            var session = SessionFactory.GetCurrentSession();
            session.Flush();
            session.Clear();
            session.Close();
            base.OnActionExecuted(actionExecutedContext);
        }
    }

步骤3-在全局配置中注册筛选器

代码语言:javascript
复制
public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            //Do other config here
            config.Filters.Add(new SessionPerRequestAttribute());
        }
    }

步骤4-稍微修改一下控制器,

代码语言:javascript
复制
public class CategoryController : ApiController
{
    private readonly ICategoryMapper _categoryMapper;
    private readonly IHttpCategoryFetcher _categoryFetcher;

    public CategoryController(
        ICategoryMapper categoryMapper,
        IHttpCategoryFetcher categoryFetcher)
    {
        _categoryMapper = categoryMapper;
        _categoryFetcher = categoryFetcher;
    }

    public IEnumerable<Category> Get()
    {
        var session = SessionFactory.GetCurrentSession();
        return session 
            .QueryOver<Data.Model.Category>()
            .List()
            .Select(_categoryMapper.CreateCategory)
            .ToList();
    }
}

这里发生的情况是,当请求出现时,它将创建一个新会话,并绑定到请求上下文,并且同样用于web方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29313736

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档