.net 需要一个使用nhibernate+;工作单位+;存储库模式&x2B;服务层&x2B;尼尼特
我正在使用.net 需要一个使用nhibernate+;工作单位+;存储库模式&x2B;服务层&x2B;尼尼特,.net,nhibernate,repository-pattern,unit-of-work,ninject-2,.net,Nhibernate,Repository Pattern,Unit Of Work,Ninject 2,我正在使用 nhibernate+流利的nhibernate asp.NETMVC3 尼尼特 目前,我正在使用nhibernate、ninject以及存储库模式和服务层 所以我有这个 尼尼特 这就是我所拥有的 我想使用工作单元模式,这样我就可以得到更多的委托,并正确地处理事务() 因此,我正在寻找一个简单的例子,说明如何让他们一起工作,并找出我需要改变多少我到目前为止所得到的 我看到的大多数教程都比我想要的更复杂。大多数人都做TDD,让通用存储库变得更好,但在我进入那个阶段之前,我希望看到一
- nhibernate+流利的nhibernate
- asp.NETMVC3
- 尼尼特
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISessionFactory>().ToProvider<NhibernateSessionFactoryProvider>().InSingletonScope();
kernel.Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
kernel.Bind<ITable1Repo>().To<Table1Repo>();
kernel.Bind<ITable1Service>().To<Table1Service>();
kernel.Bind<IUnitofWork>().To<UnitofWork>();
}
所以我一直在研究它,并提出了这个非常简单的例子。我不确定我是否做对了 Ninject
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISessionFactory>().ToProvider<NhibernateSessionFactoryProvider>().InSingletonScope();
kernel.Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
kernel.Bind<ITable1Repo>().To<Table1Repo>();
kernel.Bind<ITable1Service>().To<Table1Service>();
kernel.Bind<IUnitofWork>().To<UnitofWork>();
}
//域
public class Table1
{
public virtual int Id { get; private set; }
public virtual string C1 { get; set; }
public virtual string C2 { get; set; }
}
//流畅映射
public class Table1Mapping : ClassMap<Table1>
{
public Table1Mapping()
{
Id(x => x.Id);
Map(x => x.C1);
Map(x => x.C2);
}
}
//服务层
public class Table1Service : unitofwork.Models.Service.ITable1Service
{
private readonly ITable1Repo table1Repo;
private readonly IUnitofWork unitOfWork;
public Table1Service(ITable1Repo table1Repo, IUnitofWork unitOfWork)
{
this.table1Repo = table1Repo;
this.unitOfWork = unitOfWork;
}
public void Save()
{
Table1 a = new Table1();
a.C1 = "test";
a.C2 = "test2";
table1Repo.Create(a);
unitOfWork.Commit();
}
}
//工作单位
public class UnitofWork : unitofwork.Models.IUnitofWork
{
private readonly ITransaction transaction;
private readonly ISession session;
public UnitofWork(ISession session)
{
this.session = session;
session.FlushMode = FlushMode.Auto;
transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public void Commit()
{
if (!transaction.IsActive)
{
throw new InvalidOperationException("Oops! We don't have an active transaction");
}
transaction.Commit();
}
public void Rollback()
{
if (transaction.IsActive)
{
transaction.Rollback();
}
}
public void Dispose()
{
if (session.IsOpen)
{
session.Close();
}
}
}
我使用的是“香草”ASP.NET,而不是ASP.NETMVC3,但本质上我们也在做同样的事情 首先,我有一个单独的
UnitOfWork
类,如下所示:
public class UnitOfWork
{
private static ISessionFactory SessionFactory
{
get
{
return Container.Get<ISessionFactory>();
}
}
public static ISession Session
{
get
{
return SessionFactory.GetCurrentSession();
}
}
public static void Start()
{
CurrentSessionContext.Bind(SessionFactory.OpenSession());
Session.FlushMode = FlushMode.Commit;
Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public static void Rollback()
{
Rollback(true);
}
/// <summary>
/// Rollback the current transaction, and optionally start a new transaction
/// </summary>
/// <param name="startNew">Whether to start a new transaction and keep the session open</param>
public static void Rollback(bool startNew)
{
ISession session = CurrentSessionContext.Unbind(SessionFactory);
if (session != null)
{
// Rollback current transaction
if (session.Transaction.IsActive && !session.Transaction.WasRolledBack)
{
session.Transaction.Rollback();
}
// Close and discard the current session
session.Close();
session.Dispose();
session = null;
}
if (startNew)
{
Start();
}
}
/// <summary>
/// Commit the current transaction, keeping the current session open and starting a new transaction
///
/// Call Commit multiple times during a single unit of work if you want to commit database changes in
/// multiple transactions
/// </summary>
public static void Commit()
{
Commit(true);
}
/// <summary>
/// Commit the current transaction, and optionally keep the session open and start a new transaction
///
/// Call Commit multiple times during a single unit of work if you want to commit database changes in
/// multiple transactions
/// </summary>
/// <param name="startNew">Whether to start a new transaction and keep the session open</param>
public static void Commit(bool startNew)
{
if (startNew)
{
Session.Transaction.Commit();
Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
else
{
ISession session = CurrentSessionContext.Unbind(SessionFactory);
if (session != null)
{
if (session.Transaction.IsActive && !session.Transaction.WasRolledBack)
{
session.Transaction.Commit();
}
session.Close();
session.Dispose();
session = null;
}
}
}
}
因此,每个web请求都会启动一个新的工作单元,如果没有未处理的异常,则会自动提交。当然,如果需要,您可以在web请求中手动调用UnitOfWork.Commit()
或UnitOfWork.Rollback()
。行standariocsetup.Initialise…
使用Ninject模块配置NHibernate,与您已经在做的基本相同
因此,从本质上讲,在现有工作单元的基础上增加一个工作单元并不需要做很多工作。每个工作单元都需要一个新的会话。我知道这是一篇老文章,但我很好奇-静态会话方法对重叠请求来说不是一个潜在问题吗?@MikeKantor这不是问题,当我们让NHibernate管理会话上下文时,
会话
getter可能是静态的,但它返回的内容取决于我们配置的会话上下文。在本例中,我们使用的是“web”会话上下文,它在每个请求中使用一个会话(我相信是通过将它存储在HttpContext.Current.Items
)。回顾过去,让所有东西都在UnitOfWork
类上保持静态看起来确实有点难看。我可能只会使用实例道具/方法,并将UnitOfWork
实例注入到需要它的类中。
public class Table1Repo : unitofwork.Models.Repository.ITable1Repo
{
private readonly ISession session;
public Table1Repo(ISession session)
{
this.session = session;
}
public void Create(Table1 tbl1)
{
session.Save(tbl1);
}
}
public class Table1Service : unitofwork.Models.Service.ITable1Service
{
private readonly ITable1Repo table1Repo;
private readonly IUnitofWork unitOfWork;
public Table1Service(ITable1Repo table1Repo, IUnitofWork unitOfWork)
{
this.table1Repo = table1Repo;
this.unitOfWork = unitOfWork;
}
public void Save()
{
Table1 a = new Table1();
a.C1 = "test";
a.C2 = "test2";
table1Repo.Create(a);
unitOfWork.Commit();
}
}
public class UnitofWork : unitofwork.Models.IUnitofWork
{
private readonly ITransaction transaction;
private readonly ISession session;
public UnitofWork(ISession session)
{
this.session = session;
session.FlushMode = FlushMode.Auto;
transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public void Commit()
{
if (!transaction.IsActive)
{
throw new InvalidOperationException("Oops! We don't have an active transaction");
}
transaction.Commit();
}
public void Rollback()
{
if (transaction.IsActive)
{
transaction.Rollback();
}
}
public void Dispose()
{
if (session.IsOpen)
{
session.Close();
}
}
}
public class UnitOfWork
{
private static ISessionFactory SessionFactory
{
get
{
return Container.Get<ISessionFactory>();
}
}
public static ISession Session
{
get
{
return SessionFactory.GetCurrentSession();
}
}
public static void Start()
{
CurrentSessionContext.Bind(SessionFactory.OpenSession());
Session.FlushMode = FlushMode.Commit;
Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public static void Rollback()
{
Rollback(true);
}
/// <summary>
/// Rollback the current transaction, and optionally start a new transaction
/// </summary>
/// <param name="startNew">Whether to start a new transaction and keep the session open</param>
public static void Rollback(bool startNew)
{
ISession session = CurrentSessionContext.Unbind(SessionFactory);
if (session != null)
{
// Rollback current transaction
if (session.Transaction.IsActive && !session.Transaction.WasRolledBack)
{
session.Transaction.Rollback();
}
// Close and discard the current session
session.Close();
session.Dispose();
session = null;
}
if (startNew)
{
Start();
}
}
/// <summary>
/// Commit the current transaction, keeping the current session open and starting a new transaction
///
/// Call Commit multiple times during a single unit of work if you want to commit database changes in
/// multiple transactions
/// </summary>
public static void Commit()
{
Commit(true);
}
/// <summary>
/// Commit the current transaction, and optionally keep the session open and start a new transaction
///
/// Call Commit multiple times during a single unit of work if you want to commit database changes in
/// multiple transactions
/// </summary>
/// <param name="startNew">Whether to start a new transaction and keep the session open</param>
public static void Commit(bool startNew)
{
if (startNew)
{
Session.Transaction.Commit();
Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
else
{
ISession session = CurrentSessionContext.Unbind(SessionFactory);
if (session != null)
{
if (session.Transaction.IsActive && !session.Transaction.WasRolledBack)
{
session.Transaction.Commit();
}
session.Close();
session.Dispose();
session = null;
}
}
}
}
public class IoCHttpModule : IHttpModule, IDisposable
{
private HttpApplication httpApplication;
public void Init(HttpApplication context)
{
if (context == null)
throw new ArgumentException("context");
this.httpApplication = context;
this.httpApplication.BeginRequest += new EventHandler(BeginRequest);
this.httpApplication.EndRequest += new EventHandler(EndRequest);
this.httpApplication.Error += new EventHandler(Error);
StandardIoCSetup.Initialise(SessionContextType.Web);
}
private void BeginRequest(object sender, EventArgs e)
{
UnitOfWork.Start();
}
private void EndRequest(object sender, EventArgs e)
{
UnitOfWork.Commit(false);
}
private void Error(object sender, EventArgs e)
{
UnitOfWork.Rollback(false);
}
public void Dispose()
{
if (this.httpApplication == null)
return;
this.httpApplication.Dispose();
}
}