我有一个多项目MVC 5解决方案,其中NHibernate存储库在Core.Data
类库中声明,但我的会话管理在Wen API Core.Api
项目中。它根据请求创建和销毁会话:
public override void OnActionExecuting(HttpActionContext actionContext)
{
// start a session
var session = SessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
session.BeginTransaction();
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
// commit the current session
var session = SessionFactory.GetCurrentSession();
var transaction = session.Transaction;
if (transaction != null && transaction.IsActive)
{
transaction.Commit();
}
session = CurrentSessionContext.Unbind(SessionFactory);
session.Close();
}
现在,当我在控制器操作中实例化存储库时,我希望将此特定会话注入存储库。我怎样才能做到这一点?我可以用一个找到会话的构造函数做BaseRepository<T>: IRepository<T>
,但我真的很喜欢它注入。我怎样才能做到这一点?
答案 0 :(得分:1)
这是我们如何做的片段。
public class UnityConfig
{
private static readonly Lazy<IUnityContainer> _container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
//easy access to the container from anywhere in the application
public static T Resolve<T>()
{
//uses the Resolve<T> extension method
return GetConfiguredContainer().Resolve<T>();
}
private static void Register(IUnityContainer container)
{
container.RegisterType<IRepository, Repository>(
new InjectionConstructor(new ResolvedParameter<ISession>()));
container.RegisterType<ISession>(new PerRequestLifetimeManager(),
new InjectionFactory(c =>
c.Resolve<ISessionFactory>().OpenSession()
));
container
.RegisterType<ISessionFactory>(
new ContainerControlledLifetimeManager(),
new InjectionFactory(c =>
{
var v =
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(d => d.FromConnectionStringWithKey("web.config.connection.string.key"))
.ShowSql()
.Dialect<CustomOcMsSqlDialect>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<IRepository>()
.Conventions.AddFromAssemblyOf<IRepository>())
.BuildSessionFactory();
return v;
})
);
}
}
public interface IRepository
{
}
public class Repository : IRepository
{
private readonly ISession _session;
public Repository(ISession session)
{
_session = session;
}
}
public class SomeController : Controller
{
public ActionResult SomeAction()
{
var repo = UnityConfig.Resolve<IRepository>();
var dbEntity = repo.Load(123);
return View("SomeView");
}
}
我们通过统一连接存储库,会话和会话工厂。工厂设置为ContainerControlled
(统一单身)。会话设置为PerRequest
,因此我们为每个请求获取一个新会话。并且存储库使用常规生命周期管理器,因此我们为每个解析获得一个新的。
通过这种方式,您可以对存储库请求统一,并在整个请求中获得相同的会话。它还将在请求结束时自动处理会话。但我相信你可以参加ApplicationEndRequest活动并做一些大扫除,如果你想要的话。
希望这有帮助!