nhibernate プロファイラーを使用してサイトをスローすると、このメッセージが表示されました
警告: 暗黙的なトランザクションの使用はお勧めできません
http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions
それらはすべてのselectステートメントにあることがわかります。
private readonly ISession session;
public OrderHistoryRepo(ISession session)
{
this.session = session;
}
public void Save(OrderHistory orderHistory)
{
session.Save(orderHistory);
}
public List<OrderHistory> GetOrderHistory(Guid Id)
{
List<OrderHistory> orderHistories = session.Query<OrderHistory>().Where(x => x.Id == Id).ToList();
return orderHistories;
}
public void Commit()
{
using (ITransaction transaction = session.BeginTransaction())
{
transaction.Commit();
}
}
コミットと同じように、トランザクションで GetOrderHistory をラップする必要がありますか?
編集
selectステートメントをトランザクションでどのようにラップしますか? こんな感じでしょうか?ただし、「トランザクション」は使用されません。
public List<OrderHistory> GetOrderHistory(Guid Id)
{
using (ITransaction transaction = session.BeginTransaction())
{
List<OrderHistory> orderHistories = session.Query<OrderHistory>().Where(x => x.Id == Id).ToList();
return orderHistories;
}
}
編集
Ninject (セッションを取得したときのように、それを活用して私を助けることができるかもしれません)
public class NhibernateSessionFactory
{
public ISessionFactory GetSessionFactory()
{
ISessionFactory fluentConfiguration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("ConnectionString")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Map>().Conventions.Add(ForeignKey.EndsWith("Id")))
.ExposeConfiguration(cfg => cfg.SetProperty("adonet.batch_size", "20"))
//.ExposeConfiguration(BuidSchema)
.BuildSessionFactory();
return fluentConfiguration;
}
private static void BuidSchema(NHibernate.Cfg.Configuration config)
{
new NHibernate.Tool.hbm2ddl.SchemaExport(config).Create(false, true);
}
}
public class NhibernateSessionFactoryProvider : Provider<ISessionFactory>
{
protected override ISessionFactory CreateInstance(IContext context)
{
var sessionFactory = new NhibernateSessionFactory();
return sessionFactory.GetSessionFactory();
}
}
public class NhibernateModule : NinjectModule
{
public override void Load()
{
Bind<ISessionFactory>().ToProvider<NhibernateSessionFactoryProvider>().InSingletonScope();
Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
}
}
編集 3
私がこれをしたら
public List<OrderHistory> GetOrderHistory(Guid Id)
{
using (ITransaction transaction = session.BeginTransaction())
{
List<OrderHistory> orderHistories = session.Query<OrderHistory>().Where(x => x.Id == Id).ToList();
return orderHistories;
}
}
私がこれをしたら
public List<OrderHistory> GetOrderHistory(Guid Id)
{
using (ITransaction transaction = session.BeginTransaction())
{
List<OrderHistory> orderHistories = session.Query<OrderHistory>().Where(x => x.Id == Id).ToList().ConvertToLocalTime(timezoneId);
transaction.Commit();
return orderHistories;
}
}
エラーを取り除くことはできますが、予期しない結果が生じる可能性があります。
たとえば、orderHistories を取得すると、それらすべてをループして、「購入日」をユーザーの現地時間に変換します。これは、リスト用に作成した拡張メソッドを介して行われます。
変換したら、オブジェクトの「購入日」を上書きするように設定しました。この方法では、フィールドを 1 回変更するたびに新しいオブジェクトを作成する必要がありません。
コミットを呼び出す前にこの日付の変換を行うと、nhibernate はオブジェクトを更新したと判断し、コミットする必要があります。
だから私はこの質問に賞金をかけています。
- 各メソッドをトランザクションでラップする必要がないように、メソッドを作成するにはどうすればよいですか? 私はすでにセッションにninjectを使用しているので、それを活用できるかもしれませんが、1回のリクエストで複数のトランザクションを実行する必要があります。
したがって、リクエストごとに1つのトランザクションしかないことがソウルションであることはわかりません。
一時的な使用のために変更しているオブジェクトが誤ってコミットされないようにするにはどうすればよいですか?
サービスレイヤーで使用している遅延読み込みを行うにはどうすればよいですか。遅延読み込みは通常サービス層で使用されるため、トランザクションで囲みたくありません。
リポジトリ パターンを使用している場合、それを行う方法の例を見つけるのは非常に難しいと思います。例では、すべてが常に同じトランザクションで記述されており、サービス層にトランザクションを持ちたくありません (ビジネス ロジックではなくレポの仕事です)。