目前我的存储库有2个构造函数。当我从我的mvc网站上调用这些时,我总是调用第一个构造函数,从而打开一个新的会话。我应该在会议上通过吗?我该怎么做呢
public CompanyRepository()
{
_session = NHibernateHelper.OpenSession();
}
public CompanyRepository(ISession session)
{
_session = session;
}
public class NHibernateHelper
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
{
var configuration = new Configuration();
configuration.Configure();
configuration.AddAssembly(typeof(UserProfile).Assembly);
configuration.SetProperty(NHibernate.Cfg.Environment.ConnectionStringName,
System.Environment.MachineName);
_sessionFactory = configuration.BuildSessionFactory();
}
return _sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
我正在使用Ninject IOC容器(对我来说很新)。我有以下容器。我如何将ISession绑定到CompanyRepository。
private class EStoreDependencies : NinjectModule
{
public override void Load()
{
Bind<ICompanyRepository>().To<CompanyRepository>();
Bind<IUserProfileRepository>().To<UserProfileRepository>();
Bind<IAddressRepository>().To<AddressRepository>();
Bind<IRolesService>().To<AspNetRoleProviderWrapper>();
Bind<IUserService>().To<AspNetMembershipProviderWrapper>();
Bind<ICurrentUserSerivce>().To<DefaultCurrentUserSerivce>();
Bind<IPasswordService>().To<AspNetMembershipProviderWrapper>();
Bind<IStatusResponseRepository>().To<StatusResponseRepository>();
Bind<ICategoryRepository>().To<CategoryRepository>();
Bind<IProductRepository>().To<ProductRepository>();
}
}
答案 0 :(得分:3)
您应该使用“每个请求一个会话”模式,方法是将ISession对象存储在HttpContext中,并在存储库和同一HTTP请求期间进行的查询之间共享。
这是一个implementation using MVC action attributes。
通过简单地改变你的NHibernateHelper类也可以实现简单/基本的实现:
public class NHibernateHelper {
//...
const string SessionKey = "NhibernateSessionPerRequest";
public static ISession OpenSession(){
var context = HttpContext.Current;
if(context != null && context.Items.ContainsKey(SessionKey)){
//Return already open ISession
return (ISession)context.Items[SessionKey];
}
else{
//Create new ISession and store in HttpContext
var newSession = SessionFactory.OpenSession();
if(context != null)
context.Items[SessionKey] = newSession;
return newSession;
}
}
}
代码既没有编译也没有经过测试......但是应该可以工作。
答案 1 :(得分:1)
您的代码或最好是依赖注入应始终将ISession传递到存储库的构造函数中。这允许多个存储库参与单个事务。
我第二次推荐Paco让依赖注入框架为你处理这个问题。这种方法面临的挑战是非Web应用程序没有像HTTP请求 - 响应周期那样的干净的工作单元边界。我们拥有Windows窗体和ASP.NET应用程序共享的存储库,我们手动管理Windows窗体应用程序中的新增存储库。
答案 2 :(得分:0)
使用控制容器的反转
答案 3 :(得分:0)
尝试使用sessionFactory.GetCurrentSession(),它允许您访问contextual session。
这基本上允许您使用另一个答案中描述的'每个请求的会话'模型,而无需自己编写代码。
您甚至可以选择您的上下文:Http(如您的示例所示)或其他一些(我使用CallSessionContext
进行单元测试)。