Asp.net mvc 使用Castle.Windsor实现UnitOfWork

Asp.net mvc 使用Castle.Windsor实现UnitOfWork,asp.net-mvc,fluent-nhibernate,castle-windsor,unit-of-work,Asp.net Mvc,Fluent Nhibernate,Castle Windsor,Unit Of Work,简单的问题 如何将UnitOfWork与Castle.Windsor、nHibernate和ASP.NET MVC一起使用? 现在来了解更多细节。在我试图理解UnitOfWork模式的过程中,我遇到了一些困难,这些困难都是与Castle.Windsor结合使用的直接示例,特别是在安装方式方面 这是我到目前为止的理解 工夫 IUnitOfWork接口用于声明模式 UnitOfWork类必须Commit和Rollback事务,并公开一个会话 话虽如此,这里是我的i工作单元。(我使用的是Fluen

简单的问题

如何将UnitOfWork与Castle.Windsor、nHibernate和ASP.NET MVC一起使用?

现在来了解更多细节。在我试图理解
UnitOfWork
模式的过程中,我遇到了一些困难,这些困难都是与
Castle.Windsor
结合使用的直接示例,特别是在安装方式方面

这是我到目前为止的理解

工夫
  • IUnitOfWork
    接口用于声明模式
  • UnitOfWork
    类必须
    Commit
    Rollback
    事务,并公开一个
    会话
话虽如此,这里是我的
i工作单元
。(我使用的是
Fluent nHibernate

这是我的
Castle.Windsor
容器引导程序(ASP.NET MVC)

现在,在我的
Global.asax
文件中,我有以下内容

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        // Register the Windsor Container
        ControllerBuilder.Current
            .SetControllerFactory(new Containers.WindsorControllerFactory());
    }
存储库 现在我明白了,我需要将
会话
传递到我的存储库。那么,让我假设
IMembershipRepository

class MembershipRepository : IMembershipRepository
{
   private readonly ISession session;
   public MembershipRepository(ISession session)
   {
      this.session = session;
   }

   public Member RetrieveMember(string email)
   {
      return session.Query<Member>().SingleOrDefault( i => i.Email == email );
   }
}
工作单元 这是我的
UnitOfWork
课程的逐字记录

public class UnitOfWork : IUnitOfWork
{
    private readonly ISessionFactory sessionFactory;
    private readonly ITransaction transaction;

    public UnitOfWork(ISessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
        Session = this.sessionFactory.OpenSession();
        transaction = Session.BeginTransaction();
    }

    public ISession Session { get; private set; }

    public void Dispose()
    {
        Session.Close();
        Session = null;
    }

    public void Rollback()
    {
        if (transaction.IsActive)
            transaction.Rollback();
    }

    public void Commit()
    {
        if (transaction.IsActive)
            transaction.Commit();
    }
}

您的NH会话已经是一个工作单元

所以我不知道你为什么要把它进一步抽象出来。(如果有人读到这个答案,知道我为什么会很高兴听到,老实说,我从来没有听说过你为什么需要……)

我将为每个请求实现一个简单的会话。我不知道你会如何使用温莎,因为我从未使用过它,但使用StructureMap,它相当简单

我包装structuremap工厂以保存会话工厂,并根据需要将会话注入存储库

    public static class IoC
    {
        static IoC()
        {
            ObjectFactory.Initialize(x =>
            {
                x.UseDefaultStructureMapConfigFile = false;

                // NHibernate ISessionFactory
                x.ForSingletonOf<ISessionFactory>()
                 .Use(new SessionFactoryManager().CreateSessionFactory());

                // NHibernate ISession
                x.For().HybridHttpOrThreadLocalScoped()
                 .Use(s => s.GetInstance<ISessionFactory>().OpenSession());

                x.Scan(s => s.AssembliesFromApplicationBaseDirectory());
            });

            ObjectFactory.AssertConfigurationIsValid();
        }

        public static T Resolve<T>()
        {
            return ObjectFactory.GetInstance<T>();
        }

        public static void ReleaseAndDisposeAllHttpScopedObjects()
        {
            ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
        }
    }
因此,当我调用第一个存储库时,会话被打开,当请求结束时,会话被处理。存储库有一个构造函数,它接受ISession并将其分配给属性。然后我只需解决回购问题,如:

var productRepository = IoC.Resolve<IProductRepository>();
var-productRepository=IoC.Resolve();

希望有帮助。还有很多其他的方法,这对我来说是有效的。

这是一个语言/阻抗不匹配的问题,图书馆术语与你熟悉的行话不一致吗

我对这个[流利的]nhibernate也很陌生,所以我仍在努力想办法,但我的看法是:

通常,将ISession与应用程序会话关联(例如,如果它是Web应用程序,您可能会考虑将会话的创建与AppultIsPoad事件关联起来,并在应用程序关闭时处理)。当应用程序的范围消失时,存储库也应该消失

UnitOfWork只是包装/抽象事务的一种方式,在更新过程中有多个操作要执行,为了保持一致,它们必须按顺序完成,并且每个操作都要成功。例如,在数据创建、分析或转换中应用不只是琐碎的业务规则时

下面是一篇博客文章的链接,它提供了一个以流畅的方式使用ISession和UnitOfWork的示例。


编辑:只是强调一下,我认为您不必为针对存储库的每个操作使用一个工作单元。只有当事务是唯一合理的选择时,才真正需要UnitOfWork,但我也只是从这个开始。

这确实有帮助-我不会像您所展示的那样使用单例静态模式,但我理解您所说的<代码>会话是工作单元。我需要在我的存储库中使用
ISession
实现
try
catch
逻辑,而不是试图为它重新发明轮子。这只是我的IoC的包装。它为每个请求连接一个ISession。如果希望每次调用都有一个会话,则可以在存储库中使用(var Session=IoC.Resolve().OpenSession())写入
public class UnitOfWork : IUnitOfWork
{
    private readonly ISessionFactory sessionFactory;
    private readonly ITransaction transaction;

    public UnitOfWork(ISessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
        Session = this.sessionFactory.OpenSession();
        transaction = Session.BeginTransaction();
    }

    public ISession Session { get; private set; }

    public void Dispose()
    {
        Session.Close();
        Session = null;
    }

    public void Rollback()
    {
        if (transaction.IsActive)
            transaction.Rollback();
    }

    public void Commit()
    {
        if (transaction.IsActive)
            transaction.Commit();
    }
}
    public static class IoC
    {
        static IoC()
        {
            ObjectFactory.Initialize(x =>
            {
                x.UseDefaultStructureMapConfigFile = false;

                // NHibernate ISessionFactory
                x.ForSingletonOf<ISessionFactory>()
                 .Use(new SessionFactoryManager().CreateSessionFactory());

                // NHibernate ISession
                x.For().HybridHttpOrThreadLocalScoped()
                 .Use(s => s.GetInstance<ISessionFactory>().OpenSession());

                x.Scan(s => s.AssembliesFromApplicationBaseDirectory());
            });

            ObjectFactory.AssertConfigurationIsValid();
        }

        public static T Resolve<T>()
        {
            return ObjectFactory.GetInstance<T>();
        }

        public static void ReleaseAndDisposeAllHttpScopedObjects()
        {
            ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
        }
    }
        protected void Application_EndRequest(object sender, EventArgs e)
        {
            IoC.ReleaseAndDisposeAllHttpScopedObjects();
        }
var productRepository = IoC.Resolve<IProductRepository>();