我该如何解决这个问题?我想注入一个 nhibernate 会话,但会话尚未创建
编辑
我想尝试执行 Remo Gloor 建议的操作
- 创建一个为 Provider 派生的 SessionFactoryProvider,使用 OnApplicationStarted 中的代码重新运行 SessionFactory
- 使用新的提供程序为 SessionFactory 创建一个绑定并将其放入 SingletonScope
- Create一个从 Provider 派生的 SessionProvider,它获取在构造函数中注入的 SessionFactory,并使用工厂的 GetCurrentSession 重新启动一个新会话。
- 使用打开、传输、回滚和关闭会话的激活和停用操作(基本上是来自 Application_BeginRequest、EndRequest 的代码)创建 ISession 到上述提供程序的绑定。按照请求范围声明绑定。
- 删除Application_BeginRequest、EndRequest。
- 使用 Bind().To() 绑定存储库;
我正在寻找一个能够解决这些问题的教程,并提供一个我可以下载和使用的文件。如果它使用大量泛型,你需要非常详细,因为泛型仍然让我着迷。
您好,
我正在尝试根据请求与我的 nhibernate 进行会话。
我在我的 global.aspx 中完成了此操作
using System;
using System.Web.Mvc;
using System.Web.Routing;
using Demo.WebUI.Models.NinjectModules;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Context;
using Ninject;
using Ninject.Modules;
using Ninject.Web.Mvc;
namespace Demo.WebUI
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Account", action = "Login", id = UrlParameter.Optional} // Parameter defaults
);
}
public static ISessionFactory SessionFactory { get; private set; }
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
SessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Demo.Framework.Data.NhibernateMapping.UserMap>())
.ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web"))
.ExposeConfiguration(BuidSchema)
.BuildSessionFactory();
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
ISession session = SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
}
protected void Application_EndRequest(object sender, EventArgs e)
{
ISession session = CurrentSessionContext.Unbind(SessionFactory);
if (session != null)
{
try
{
session.Transaction.Commit();
}
catch (Exception)
{
session.Transaction.Rollback();
}
finally
{
session.Close();
session.Dispose();
}
}
}
protected override IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new ServiceModule(),
new RepoModule()
};
return new StandardKernel(modules);
}
private static void BuidSchema(NHibernate.Cfg.Configuration config)
{
new NHibernate.Tool.hbm2ddl.SchemaExport(config).Create(false, true);
}
}
}
在我的 RepoModule 中,
Bind<IUserRepo>().To<UserRepo>().WithConstructorArgument("session",MvcApplication.SessionFactory.GetCurrentSession());
这将引发错误,因为 ninject 将在 OnApplicationStarted() 启动之前和 Application_Begin 开始绑定它之前创建内核。
那我该怎么办呢?
编辑
这是我在一些教程中找到的。
public static ISessionFactory SessionFactory { get; private set; }
public MvcApplication()
{
SessionFactory = CreateSessionFactory();
}
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Demo.Framework.Data.NhibernateMapping.UserMap>())
.ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web"))
.ExposeConfiguration(BuidSchema)
.BuildSessionFactory();
}
我的绑定
Bind<IUserRepo>().To<UserRepo>();
Bind<ISession>().ToMethod(x => MvcApplication.SessionFactory.GetCurrentSession());
因此,我首先在构造函数加载时创建会话工厂,然后将其绑定到 Isession,而不是将其作为参数传递。
我对全局 aspx 唯一不确定的是它是否会每次都继续调用构造函数并重新创建 SessionFactory 什么是不好的。所以我不确定是否需要先检查它是否存在。
Edit
I would like to try to do what Remo Gloor has recommended
- Create a SessionFactoryProvider derived for Provider that retruns a SessionFactory using the code in OnApplicationStarted
- Create a binding for SessionFactory using the new provider and put it in SingletonScope
- Create a SessionProvider derived from Provider that gets the SessionFactory injected in the constructor and retuns a new session using GetCurrentSession of the factory.
- Create a binding for ISession to the above provider with activation and deactivation actions that open, transmit, rollback, and close the session (basiclly the code from Application_BeginRequest, EndRequest). Decalre the binding as in request scope.
- Remove Application_BeginRequest, EndRequest.
- Bind the repo using Bind().To();
I am looking for a tutorial that hits on these points with a file that I can download and play around with. If it uses lots of generics you needs to be pretty detailed as generics still get me.
Hi
I am trying to do session per request with my nhibernate.
I done this in my global.aspx
using System;
using System.Web.Mvc;
using System.Web.Routing;
using Demo.WebUI.Models.NinjectModules;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Context;
using Ninject;
using Ninject.Modules;
using Ninject.Web.Mvc;
namespace Demo.WebUI
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Account", action = "Login", id = UrlParameter.Optional} // Parameter defaults
);
}
public static ISessionFactory SessionFactory { get; private set; }
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
SessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Demo.Framework.Data.NhibernateMapping.UserMap>())
.ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web"))
.ExposeConfiguration(BuidSchema)
.BuildSessionFactory();
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
ISession session = SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
}
protected void Application_EndRequest(object sender, EventArgs e)
{
ISession session = CurrentSessionContext.Unbind(SessionFactory);
if (session != null)
{
try
{
session.Transaction.Commit();
}
catch (Exception)
{
session.Transaction.Rollback();
}
finally
{
session.Close();
session.Dispose();
}
}
}
protected override IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new ServiceModule(),
new RepoModule()
};
return new StandardKernel(modules);
}
private static void BuidSchema(NHibernate.Cfg.Configuration config)
{
new NHibernate.Tool.hbm2ddl.SchemaExport(config).Create(false, true);
}
}
}
In my RepoModule I have
Bind<IUserRepo>().To<UserRepo>().WithConstructorArgument("session",MvcApplication.SessionFactory.GetCurrentSession());
This will throw a error because ninject will create the kernal before OnApplicationStarted() gets started and before Application_Begin starts to bind it.
So what should I do?
Edit
This is what I found in some tutorial.
public static ISessionFactory SessionFactory { get; private set; }
public MvcApplication()
{
SessionFactory = CreateSessionFactory();
}
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Demo.Framework.Data.NhibernateMapping.UserMap>())
.ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web"))
.ExposeConfiguration(BuidSchema)
.BuildSessionFactory();
}
My binding
Bind<IUserRepo>().To<UserRepo>();
Bind<ISession>().ToMethod(x => MvcApplication.SessionFactory.GetCurrentSession());
So I first create the session factory on constructor load then I bind it to the Isession instead of passing it in as a parameter.
The only thing that I am not sure with the global aspx is if it will keep calling the constructor up everytime and recreating the SessionFactory what is bad. So I am not sure if I need to check if it exists first.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的实现很好,但不是一个好的解决方案,因为您手动控制会话生命周期。实际的做法是让 Ninject 决定何时创建、打开、关闭和处置会话。
例如,想象一下不需要任何会话的操作。或者是一个更大的项目,其中有多个数据库和会话来分配负载。在这些情况下,您不希望为每个操作创建所有可能的会话,因为这意味着可以避免的开销。您宁愿只创建当前操作所需的那些。
为此,需要进行几项更改:
Bind().To();
绑定存储库Your implementation is fine but not a good solution as you do manual control of the session lifecycle. The actual way this should be done is to let Ninject decide when the session is created, opened, closed and disposed.
E.g. imagine actions where you don't need any session. Or a larger project where you have several databases and sessions to split the load. In these situations you don't want all the possible sessions be created for each action as this means an avoidable overhead. You rather want that only those are created that are required for the current action.
To do so several changes are required:
Bind<IUserRepo>().To<UserRepo>();
我最近在博客中介绍了如何在带有存储库模式的 asp.net mvc 应用程序中使用 nhibernate。这个项目提供了一个使用nhibernate & 的例子。宁注射。以下是一些链接:
http://blog。 bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to- Fluent-nhibernate- and-mysql/
http://blog. bobcravens.com/2010/09/the-repository-pattern-part-2/
http://blog.bobcravens.com/2010/11/using-ninject-to-manage-ritic-resources/
我认为我们有类似的架构。查看帖子,如果您有任何疑问,请告诉我。
,您可以在 http://gpsnerd.codeplex.com 下载该项目
顺便说一句
I recently blogged about using nhibernate in an asp.net mvc application with a repository pattern. This project provides an example of using nhibernate & ninject. Here are a few links:
http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/
http://blog.bobcravens.com/2010/09/the-repository-pattern-part-2/
http://blog.bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/
I think that we have a similar architecture. Take a look at the posts and let me know if you have any questions.
BTW, you can download this project at http://gpsnerd.codeplex.com
Bob
将 SessionFactory 初始化代码包装在单例中,当您访问会话工厂的“Instance”属性时,它将初始化并配置会话工厂一次。在 BeginRequest 中使用它而不是当前代码。
Wrap the SessionFactory initialization code in a singleton, that will initialize and configure the sessionfactory once when you access the "Instance" property on it. Use this in BeginRequest instead of current code.
您正在使用当前会话上下文,无需注入会话!
相反,注入 SessionFactory,然后使用
GetCurrentSession()
获取ISession
。更改后,您可以使用 Felice 的解决方案。
You're using a current session context, you don't have to inject the session!
Inject the SessionFactory instead, then use
GetCurrentSession()
to obtain anISession
.After that change, you can use Felice's solution.