我的 ASP.NET MVC 4 项目正在使用 NHibernate(存储库后面)和 Castle Windsor,使用 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);
}
}
NHibernateInstaller 直接来自NHib Facility Quickstart。
我在我的基础存储库中使用 ISessionManager ...
protected ISession Session
{
get
{
return _sessionManager.OpenSession();
}
}
public virtual T Commit(T entity)
{
Session.SaveOrUpdate(entity);
return entity;
}
最后,导致问题的我的应用程序代码:
[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。或者可能没有提交事务?
我已经在网上搜索了几个小时,现在试图解决这个问题,作为最后的绝望行为,我已经在 SO 上发布了。有任何想法吗?:)
哦,在 NHProf 中,我看到了三个会话(1 个用于来自 repo 的 GetPrescriber 调用,一个用于更新(没有 sql)- 一个用于我对基类的 actionfilter 中的某些操作)。我还收到有关使用隐式事务的警报。这让我很困惑,因为我认为我正在做我需要做的一切来获得交易——使用 AutoTx 和 Transaction 属性。根据我的 Windsor 配置,我还希望每个 web 请求只有 1 个会话。
更新:似乎在花一天时间阅读 NHibernateFacility 和 AutoTx Facility 的源代码以进行自动交易之后,AutoTx 没有在我的 INHibernateInstaller 实现上设置拦截器。这似乎意味着每当 SessionManager 调用 OpenSession 时,它都会调用不带参数的默认版本,而不是接受拦截器的版本。AutoTxFacility 在内部向 windsor 注册 TransactionInterceptor,以便可以通过使用 AutoTx 的 TransactionalComponentInspector 的 Windsor 在我的 INHibernateInstaller 混凝土上添加拦截器