私のASP.NETMVC4プロジェクトは、AutoTxとNHibernateファシリティを使用して、NHibernate(リポジトリの背後)とCastleWindsorを使用しています。私は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ファシリティクイックスタートから直接取得されます。
ベースリポジトリで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では3つのセッションが表示されます(1つはリポジトリからのGetPrescriber呼び出し用、1つは更新用(SQLなし)、もう1つは基本クラスのactionfilterのアクション用)。また、暗黙のトランザクションの使用に関するアラートを受け取ります。AutoTxとTransaction属性を使用して、トランザクションを取得するために必要なすべてのことを実行していると思ったため、これは混乱を招きます。また、Windsorの構成に従って、Webリクエストごとに1つのセッションしかないことも期待していました。
更新:自動トランザクション用のNHibernateFacilityとAutoTxファシリティのソースを読んで一日を過ごした後、AutoTxはINHibernateInstallerの実装にインターセプターを設定していないようです。これは、SessionManagerがOpenSessionを呼び出すときは常に、インターセプターを受け入れるバージョンではなく、パラメーターなしのデフォルトバージョンを呼び出していることを意味しているようです。AutoTxFacilityはTransactionInterceptorをwindsorに内部的に登録するため、WindsorはAutoTxのTransactionalComponentInspectorを利用して、INHibernateInstallerコンクリートにInterceptorを追加できます。