Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/nhibernate/3.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不保留对我的对象的更改_Nhibernate_Asp.net Mvc 4_Castle Windsor - Fatal编程技术网

NHibernate不保留对我的对象的更改

NHibernate不保留对我的对象的更改,nhibernate,asp.net-mvc-4,castle-windsor,Nhibernate,Asp.net Mvc 4,Castle Windsor,我的ASP.NETMVC4项目使用NHibernate(存储库后面)和CastleWindsor,使用AutoTx和NHibernate设施。我遵循了haf和我的同事编写的指南,我可以创建和读取对象 我的PersistenceInstaller如下所示 public class PersistenceInstaller : IWindsorInstaller { public void Install(Castle.Windsor.IWindsorContainer container,

我的ASP.NETMVC4项目使用NHibernate(存储库后面)和CastleWindsor,使用AutoTx和NHibernate设施。我遵循了haf和我的同事编写的指南,我可以创建和读取对象

我的PersistenceInstaller如下所示

public class PersistenceInstaller : IWindsorInstaller
{
    public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
    {
        container.AddFacility<AutoTxFacility>();            
        container.Register(Component.For<INHibernateInstaller>().ImplementedBy<NHibernateInstaller>().LifeStyle.Singleton);
        container.AddFacility<NHibernateFacility>(
            f => f.DefaultLifeStyle = DefaultSessionLifeStyleOption.SessionPerWebRequest);          
    }
}
最后,是导致问题的应用程序代码:

[HttpPost]
[ValidateAntiForgeryToken]        
[Transaction]
public ActionResult Maintain(PrescriberMaintainViewModel viewModel)
{           
    if (ModelState.IsValid)
    {
        var prescriber = UserRepository.GetPrescriber(User.Identity.Name);

        //var prescriber = new Prescriber { DateJoined = DateTime.Today, Username = "Test" };                
        prescriber.SecurityQuestion = viewModel.SecurityQuestion;
        prescriber.SecurityAnswer = viewModel.SecurityAnswer;
        prescriber.EmailAddress = viewModel.Email;
        prescriber.FirstName = viewModel.FirstName;
        prescriber.LastName = viewModel.LastName;
        prescriber.Address = new Address
                                {
                                    Address1 = viewModel.AddressLine1,
                                    Address2 = viewModel.AddressLine2,
                                    Address3 = viewModel.AddressLine3,
                                    Suburb = viewModel.Suburb,
                                    State = viewModel.State,
                                    Postcode = viewModel.Postcode,
                                    Country = string.Empty
                                };

        prescriber.MobileNumber = viewModel.MobileNumber;
        prescriber.PhoneNumber = viewModel.PhoneNumber;
        prescriber.DateOfBirth = viewModel.DateOfBirth;
        prescriber.AHPRANumber = viewModel.AhpraNumber;
        prescriber.ClinicName = viewModel.ClinicName;
        prescriber.ClinicWebUrl = viewModel.ClinicWebUrl;
        prescriber.Qualifications = viewModel.Qualifications;
        prescriber.JobTitle = viewModel.JobTitle;


        UserRepository.Commit(prescriber);          
    }

    return View(viewModel);
}
上述代码将保存一个新的处方(通过取消注释注释掉注释行等进行测试)

我正在使用NHProf,并且已经确认没有向数据库发送用于更新的sql。我可以看到正在执行读取,但仅此而已

在我看来,NHibernate不识别正在更改的实体,因此不生成sql。或者可能没有提交事务

我已经在网上搜索了几个小时,现在试图解决这个问题,作为最后的绝望行为,我已经在网上发布了。有什么想法吗?:)

哦,在NHProf中,我看到了三个会话(一个用于来自repo的GetPrescriber调用,一个用于更新(没有sql),另一个用于基类上actionfilter中的某些操作)。我还收到了关于使用隐式事务的警告。这让我很困惑,因为我认为我正在做所有我需要的事情来获得一个事务-使用AutoTx和事务属性。根据我的Windsor配置,我还希望每个webrequest只有一个会话

更新:在花了一天时间阅读NHibernateFacility的源代码和自动事务处理的AutoTx设施之后,AutoTx似乎没有在我的INHibernateInstaller实现上设置拦截器。这似乎意味着,每当SessionManager调用OpenSession时,它都会调用不带参数的默认版本,而不是接受拦截器的版本。在内部,AutoTxFacility向windsor注册TransactionInterceptor,以便windsor利用AutoTx的TransactionalComponentInspector将其添加到我的INHibernateInstaller混凝土上的拦截器中


在我看来,这就像为每次调用存储库创建会话一样。会议应涵盖整个业务运营。它应该在开始时打开,并在结束时提交和处置

这段代码中还有其他奇怪的东西

  • 提交与保存或更新是完全不同的概念
  • 而且你也不需要告诉NH去存储更改。您不需要调用会话。保存已在会话中的对象。无论如何,它们都是存储的。您只需在添加新对象时调用session.Save即可
  • 确保在整个业务操作中使用事务
在上面的代码片段中有一个最有可能是“意外”的部分。NHProf的观察结果证明了这一点

哦,在NHProf中,我看到了三次会议(1次为GetPrescripter电话会议) 从repo中,我假设一个用于更新(没有sql),另一个用于更新 我的actionfilter中的一些操作(在基类上)

调用
OpenSession()
会触发创建新的会话实例

protected ISession Session
{
    get { return _sessionManager.OpenSession(); }
}
因此,每当代码访问
Session
属性时,后面就会创建新Session实例(一次又一次)。一个会话用于get,一个会话用于udpate,一个会话用于筛选器

正如我们在这里看到的,SessionManager.OpenSession()返回的会话必须用于整个范围(工作单元、web请求…)

我们需要的Syntash,si创建一个会话(当第一次访问时),然后重用它,直到作用域的enf(然后正确关闭它、提交或回滚事务…)。无论如何,现在的第一件事是以这种方式更改
会话
属性:

ISession _session;
protected ISession Session
{
    get 
    { 
      if (_session == null)
      {
         _session = sessionFactory.OpenSession();
      }
      return _session; 
    }
}

昨天花了一整天的时间在github上的AutoTx和NHibernate设施中搜索,结果一无所获,我开始了一个干净的项目,试图复制这个问题。不幸的是,对于复制,一切都正常!我在我的源代码上运行了更新包,并下载了Castle.Transactions的新版本,运行正常。我确实对自己的代码做了一些小的调整。这是为了删除UserRepository.Commit行


我不需要修改打开会话的方式。这由SessionManager实例负责。更新到Castle.Transactions后,将识别事务属性并创建事务(NHProf中不再显示警报即可证明)。

是否有错误消息?或者只是没有保留更改?没有错误消息。只是数据库中没有sql。我想我做错了什么,我只是不知道我做错了什么谢谢。我的理解是SessionManager处理会话的创建,如果当前请求中存在会话,它将被重用。因此,我只希望看到一次会议。回到Nhibernate Facility wiki条目,我看到它在上周更新了一些重要信息,这些信息是我在大约一个月前改用SessionManager时没有的。我同意提交命名,但我正在处理一个在任何地方都使用提交动词的现有抽象存储库。不管Commit具有更多的事务语义,最终结果仍然是一样的。谢谢你,当然可以。正如我在Stefans answer中所评论的,当我添加SessionManager时,NHib Facility wiki并没有这些信息(历史视图证实了这一点:)。现在我可以在wiki中看到额外的详细信息了,我知道我需要添加IsWeb标志并连接SessionWebModule-我刚刚期望的事情得到了处理,因为wiki中没有信息-而不是使用会话工厂创建会话实例。。。干杯
ISession _session;
protected ISession Session
{
    get 
    { 
      if (_session == null)
      {
         _session = sessionFactory.OpenSession();
      }
      return _session; 
    }
}