定义了一个domain model
我想知道如何完成剩下的工作。
数据访问权限
我之前已经阅读过没有必要在UnitOfWork
上编写自己的ISession
实现代码(thogh我发现了很多关于如何做得很好的信息)。所以我很困惑..我有这样的存储库界面:
public interface IRepository<T> where T: AbstractEntity<T>, IAggregateRoot
{
T Get(Guid id);
IQueryable<T> Get(Expression<Func<T, Boolean>> predicate);
IQueryable<T> Get();
T Load(Guid id);
void Add(T entity);
void Remove(T entity);
void Remove(Guid id);
void Update(T entity);
void Update(Guid id);
}
在具体实施中,有两种选择:
选项A
是通过构造函数注入ISessionFactory
并使用类似的东西:
public class Repository<T> : IRepository<T> where T : AbstractEntity<T>, IAggregateRoot
{
private ISessionFactory sessionFactory;
public Repository(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
public T Get(Guid id)
{
using(var session = sessionFactory.OpenSession())
{
return session.Get<T>(id);
}
}
}
选项B
是使用NHibernateHelper
类
using(var session = NHibernateHelper.GetCurrentSession())
{
return session.Get<T>(id);
}
NHibernateHelper
internal sealed class NHibernateHelper
{
private const string CurrentSessionKey = "nhibernate.current_session";
private static readonly ISessionFactory sessionFactory;
static NHibernateHelper()
{
sessionFactory = new Configuration().Configure().BuildSessionFactory();
}
public static ISession GetCurrentSession()
{
HttpContext context = HttpContext.Current;
ISession currentSession = context.Items[CurrentSessionKey] as ISession;
if(currentSession == null)
{
currentSession = sessionFactory.OpenSession();
context.Items[CurrentSessionKey] = currentSession;
}
return currentSession;
}
public static void CloseSession()
{
HttpContext context = HttpContext.Current;
ISession currentSession = context.Items[CurrentSessionKey] as ISession;
if(currentSession == null)
{
return;
}
currentSession.Close();
context.Items.Remove(CurrentSessionKey);
}
public static void CloseSessionFactory()
{
if(sessionFactory != null)
{
sessionFactory.Close();
}
}
}
有什么选择?
为什么(注射除外)?
如果我使用选项A
,我在哪里放置ISessionFactory
的配置?
它应该放在ASP.NET MVC
项目的某个地方吗?怎么样?
感谢您阅读怪物问题!非常感谢您的指导!
答案 0 :(得分:2)
如何使用mvc处理注入依赖项在某种程度上是特定于版本的,但始终有助于使用真正的依赖注入(DI)容器。无论您如何切片,此解决方案都需要您将ISession注入存储库而不是ISessionFactory。这允许您的DI容器正确管理会话的生命周期。
假设您使用的是Asp.Net MVC 3并且没有附加到特定的DI容器,请启动Nuget控制台并输入:
install-package Ninject.MVC3
这将下载Ninject(这是一个DI容器)并配置你的mvc应用程序来使用它。它还将创建一个文件〜/ App_Start / NinjectMVC3.cs,您可以在其中配置依赖项。
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISessionFactory>()
.ToMethod(c => new Configuration().Configure().BuildSessionFactory())
.InSingletonScope();
kernel.Bind<ISession>()
.ToMethod((ctx) => ctx.Kernel.Get<ISessionFactory>().OpenSession())
.InRequestScope();
kernel.Bind<IRepository<>>().To<Repository<>>();
}
第一个语句告诉ninject当某些东西需要一个ISessionFactory时,它应该懒惰地初始化NHibernate并创建一个。然后,该会话工厂将作为应用程序范围内的单例保存,用于应用程序的生命周期。
第二个语句告诉ninject当某些东西需要一个ISession时,它应该得到一个ISessionFactory实例并调用OpenSession()。然后,此会话将在请求范围内重用,并在请求结束时销毁。
第三个语句告诉ninject当某些东西需要任何类型的IRepository时,它应该只是新的一个使用它的内置逻辑来解决依赖关系。
从这里你可以按如下方式编写代码,一切都应该正常工作。
public class WidgetController : Controller
{
private readonly IRepository<Widget> _repository;
public WidgetController(IRepository<Widget> repository)
{
_repository = repository;
}
}
关于存储库我想指出一篇优秀的博文Repository is the new Singleton
答案 1 :(得分:1)
我通常在我的存储库中使用只读属性,就像这样
protected ISession Session
{
get
{
return NHibernateSessionFactory.CurrentFor(dataBaseFactoryKey);
}
}
我的NHibernateSessionFactory就像this一样。
答案 2 :(得分:1)
在网络应用中,您应该根据网络请求使用模式NH会话。我认为每个Web请求应该只有一个会话,并且您的存储库应该使用此单个会话。 要实现这一点,您需要编写IHttpModule,它将打开会话,开始事务并在请求开始时将会话绑定为环境(当前)会话,并在请求结束时结束事务和关闭会话。您还需要将current_session_context_class设置为“web”。然后您的Repository / DAO将如下所示
public TEntity Get(object id)
{
return sessionFactory.GetCurrentSession().Get<TEntity>(id);
}
答案 3 :(得分:0)
MVC和NHibernate的最佳模式是每个请求的会话 步骤进行:
在 Application_Start()中配置和构建会话工厂:
var config = new Configuration()。Configure();
SessionFactory = config.BuildSessionFactory();
在 Application_BeginRequest 中打开会话并将其绑定到 CurrentSessionContext:
var nhSession = SessionFactory.OpenSession();
CurrentSessionContext.Bind(会话);
在 Application_EndRequest()取消绑定并处置会话
现在,在您的控制器中,您可以访问会话调用:
Global.SessionFactory.GetCurrentSession();
编辑:关注@hival评论
在控制器内部处理使用块中的模型,并根据您的逻辑执行提交/回滚。