Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
NHibernate会议+;使用ASP.NET MVC 3的事务_Nhibernate_Asp.net Mvc 3 - Fatal编程技术网

NHibernate会议+;使用ASP.NET MVC 3的事务

NHibernate会议+;使用ASP.NET MVC 3的事务,nhibernate,asp.net-mvc-3,Nhibernate,Asp.net Mvc 3,目前我正在编写一个新的应用程序,尽管公司的标准是使用NHibernate(因为这是所有项目的标准),但由于ASP.NET MVC 3现在已经成熟,我正在使用它。我已经在控制器中实现了我的事务(这应该是您应该执行的方式),因此在我的根控制器中看起来是这样的: [TransactionPerRequest] public class FbsController : Controller { } 然后,我的所有控制器都从此FbsController继承。之所以这样做,是因为我所有操作的90%都将转

目前我正在编写一个新的应用程序,尽管公司的标准是使用NHibernate(因为这是所有项目的标准),但由于ASP.NET MVC 3现在已经成熟,我正在使用它。我已经在控制器中实现了我的事务(这应该是您应该执行的方式),因此在我的根控制器中看起来是这样的:

[TransactionPerRequest]
public class FbsController : Controller
{

}
然后,我的所有控制器都从此
FbsController
继承。之所以这样做,是因为我所有操作的90%都将转移到数据库中,因此创建事务并处理剩余10%操作(很少执行)的事务的开销不值得用
[TransactionPerRequest]
来修饰每个操作

一直困扰我的是NHibernate课程。在repository类中,这与我所拥有的类似,尽管这在其他项目中有所不同:

    public void Add(User user)
    {
        using (ISession session = NHibernateHelper.OpenSession())
        {
            session.Save(user);
        }
    }

    public void Remove(User user)
    {
        using (ISession session = NHibernateHelper.OpenSession())
        {
            session.Delete(user);
        }
    }

    public User GetById(int userId)
    {
        using (ISession session = NHibernateHelper.OpenSession())
        {
            return session.QueryOver<User>()
                .Where(c => c.UserID == userId)
                .SingleOrDefault();
        }
    }
公共作废添加(用户)
{
使用(ISession session=NHibernateHelper.OpenSession())
{
session.Save(用户);
}
}
公共无效删除(用户)
{
使用(ISession session=NHibernateHelper.OpenSession())
{
删除(用户);
}
}
公共用户GetById(int userId)
{
使用(ISession session=NHibernateHelper.OpenSession())
{
return session.QueryOver()
.Where(c=>c.UserID==UserID)
.SingleOrDefault();
}
}
因此,对于存储库中的大多数函数,我必须打开一个会话。有没有办法避免这种行为,这样我就不必在每个存储库方法中打开会话?这似乎有点违反直觉,因为我通常必须为每一个人这样做。我想知道其他人对事务和会话问题的解决方案是什么,我看到这些问题以各种方式散落在代码中

实际上,我希望我的存储库方法如下所示:

    public void Add(User user)
    {
        session.Save(user);
    }

    public void Remove(User user)
    {
        session.Delete(user);
    }

    public User GetById(int userId)
    {
        return session.QueryOver<User>()
            .Where(c => c.UserID == userId)
            .SingleOrDefault();
    }
公共作废添加(用户)
{
session.Save(用户);
}
公共无效删除(用户)
{
删除(用户);
}
公共用户GetById(int userId)
{
return session.QueryOver()
.Where(c=>c.UserID==UserID)
.SingleOrDefault();
}

所有事情都是隐式处理的。

你可以看看Ayende Rahien的以下一系列博客文章:


  • 我使用StructureMap在第一次调用ISession时自动启动会话,然后通过HttpRequest缓存会话。这使我可以在整个请求中使用延迟加载和事务,而无需太多编码麻烦

    下面是我的引导程序的代码,它使用Fluent NHibernate和StructureMap为我设置了一切

    public class Bootstrapper
    {
        public static ISessionFactory DBSessionFactory { get; set; }
        public static ISession DBSession { get; set; }
    
        public static void InitializeObjectFactory()
        {
            ObjectFactory.Initialize(x =>
                                         {
                                             x.PullConfigurationFromAppConfig = true;
                                             x.Scan(y =>
                                                        {
                                                            y.Assembly(Assembly.GetAssembly(typeof(AccountController)));
                                                            y.Assembly(Assembly.GetAssembly(typeof(IMyProject)));
                                                            y.WithDefaultConventions();
                                                        }
                                                 );
    
                                             // these are for NHibernate
                                             x.ForRequestedType<ISessionFactory>()
                                                 .CacheBy(InstanceScope.Singleton)
                                                 .TheDefault.Is.ConstructedBy(GetDBSessionFactory);
    
                                             // open session at beginning of every http request 
                                             // (the session is disposed at end of http request in global.asax's Application_EndRequest)
                                             x.ForRequestedType<ISession>()
                                                 .CacheBy(InstanceScope.HttpContext)
                                                 .TheDefault.Is.ConstructedBy(GetDBSession);
                                         });
        }
    
        public static ISessionFactory CreateSessionFactory()
        {
            return GetFluentConfiguration()
                .BuildSessionFactory();
        }
    
        public static ISessionFactory GetDBSessionFactory()
        {
            if (DBSessionFactory == null)
            {
                DBSessionFactory = CreateSessionFactory();
            }
            return DBSessionFactory;
        }
    
        public static ISession GetDBSession()
        {
            if (DBSession == null)
            {
                DBSession = CreateSession();
            }
            return DBSession;
        }
    
        public static ISession CreateSession()
        {
            return GetDBSessionFactory()
                .OpenSession();
        }
    
        public static FluentConfiguration GetFluentConfiguration()
        {
            string commandTimeout = ConfigurationManager.AppSettings["MyDBCommandTimeout"];
            return Fluently.Configure()
                .Database(// use your db configuration )
                .Mappings(m =>
                              {
                                  m.HbmMappings
                                      .AddFromAssemblyOf<MyEO>();
                                  m.FluentMappings
                                      .AddFromAssemblyOf<MyEO>()
                                      .AddFromAssemblyOf<MyEOMap>();
                              })
                .ExposeConfiguration(
                    cfg =>
                        {
                            // command_timeout sets the timeout for the queries
                            cfg.SetProperty("command_timeout", commandTimeout);
                        }
                );
        }
    }
    
    关闭应用程序中的会话\u EndRequest():

    现在你只要打电话

    ObjectFactory.GetInstance<ISession>() 
    
    ObjectFactory.GetInstance()
    

    从任何地方(我将其包装在一个helper类中以保持代码的简单性)和StructureMap都将为您提供缓存会话。

    我会按照以下思路做一些事情:

    public class Repository<T> : IRepository<T>
    {
        private readonly ISessionFactory SessionFactory;
        public Repository(ISessionFactory sessionFactory)
        {
            SessionFactory = sessionFactory;
        }
        public ISession Session
        {
            get
            {
                return SessionFactory.GetCurrentSession();
            }
        }
        public T Get(long id)
        {
            return Session.Get<T>(id);
        }
    }
    
    在my Global.asax.cs中:

    public static ISessionFactory SessionFactory { get; set; }
    
    然后在
    应用程序\u Start
    中定义:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RegisterRoutes(RouteTable.Routes);
    
        var nhConfig = new Configuration().Configure();
        SessionFactory = nhConfig.BuildSessionFactory();
    }
    
    然后创建该类:

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class NHSession : ActionFilterAttribute
    {
        public NHSession()
        {
            Order = 100;
        }
    
        protected ISessionFactory sessionFactory
        {
            get
            {
                    return MvcApplication.SessionFactory;
            }
        }
    
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var session = sessionFactory.OpenSession();
            CurrentSessionContext.Bind(session);
            session.BeginTransaction();
        }
    
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            var session = CurrentSessionContext.Unbind(sessionFactory);
            if (session != null)
            {
                if (session.Transaction.IsActive)
                {
                    try
                    {
                        session.Transaction.Commit();
                    }
                    catch
                    {
                        session.Transaction.Rollback();
                    }
                }
                session.Close();
            }
        }
    }
    
    然后,我的通用存储库看起来大致如下:

    public class Repository<T> : IRepository<T>
    {
        private readonly ISessionFactory SessionFactory;
        public Repository(ISessionFactory sessionFactory)
        {
            SessionFactory = sessionFactory;
        }
        public ISession Session
        {
            get
            {
                return SessionFactory.GetCurrentSession();
            }
        }
        public T Get(long id)
        {
            return Session.Get<T>(id);
        }
    }
    

    这样我就能够在请求中使用工作单元。基本上,请求进入并启动会话,
    SessionFactory
    被传递到存储库的构造函数中。我在这里使用DI,但这是可选的。如果检测到错误,则在请求结束时提交会话(如果没有),则回滚会话。我建议您使用NHProf,因为它可以帮助您理解会话管理(如果设置不正确)。

    这没关系,但是如果您使用的是存储库模式,需要访问存储库中的会话,该怎么办?他没有提到这一点,会话仅在控制器中可用,因此使用QueryOver向DB发出的请求需要从控制器中完成。@Kezzer,您可以围绕
    HttpContext.Current.Items[“NHibernateSession”]编写一个包装类
    然后配置DI框架,将其传递到存储库构造函数中。非常好的链接,这正是我想要的。非常感谢。
    public class Repository<T> : IRepository<T>
    {
        private readonly ISessionFactory SessionFactory;
        public Repository(ISessionFactory sessionFactory)
        {
            SessionFactory = sessionFactory;
        }
        public ISession Session
        {
            get
            {
                return SessionFactory.GetCurrentSession();
            }
        }
        public T Get(long id)
        {
            return Session.Get<T>(id);
        }
    }
    
    public class CmsContentRepository : Repository<CmsContent>, ICmsContentRepository
    {
        public CmsContentRepository(ISessionFactory sessionFactory) : base(sessionFactory) { }
    }
    
    [NHSession]
    public ViewResult Revisions(int id)
    {
        var model = Service.CmsContentRepository.Get(id);
        return View("Revisions", model);
    }