我应该如何在事务中包装选择语句?

| 我打算将网站与nhibernate Profiler一起投放,并且收到此消息   警告:使用隐式事务是   泄气 http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions 我看到它们出现在每个选择语句中。
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封装为事务? 编辑 如何将选择语句与事务包装在一起?会是这样吗?但是,则永远不会使用“交易”。
    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时,我将遍历所有这些并将“购买日期”转换为用户本地时间。这是通过为清单创建的扩展方法完成的。 转换后,我将其设置为覆盖对象中的“购买日期”。这样,我不必为字段的一次更改创建新对象。 现在,如果我在调用commit之前进行日期转换,则nhibernate认为我已经更新了该对象并需要提交它。 因此,我在这个问题上悬赏。 如何创建我的方法,而不必在事务中包装每个方法?我已经在会话中使用ninject了,因此尽管我被迫在单个请求中执行多个事务,但是也许我可以利用它。 因此,我不知道每个请求只有一个事务是一种灵魂。 如何确保要临时更改的对象不会意外提交? 我如何在服务层中使用延迟加载。我不想将我的延迟加载内容包含在事务中,因为它通常在我的服务层中使用。 我发现在使用存储库模式时很难找到有关如何执行此操作的示例。通过这些示例,所有内容始终都写在同一笔交易中,而我不想在服务层中拥有交易(这是存储库的工作,而不是我的业务逻辑)     
已邀请:
NHibernate社区建议您将所有内容包装在事务中,而不管您在做什么。 通常,要回答第二个问题,这要视情况而定。如果这是一个Web应用程序,则应查看每次请求会话模式。在大多数基本方案中,这意味着您将为每个HTTP请求创建一个会话,在该会话中,该会话(和事务)是在发出请求并在请求结束时提交/处置时创建的。我并不是说这对您来说是正确的方法,但这是一种对大多数人都适用的通用方法。 有很多示例说明了如何完成此操作。绝对值得花时间进行搜索和阅读。 编辑:我如何执行每个请求的会话/事务的示例: 我有一个SessionModule,它从我的依赖项解析器加载会话(这是MVC3功能):
namespace My.Web
{
    public class SessionModule : IHttpModule {
        public void Init(HttpApplication context) {
            context.BeginRequest += context_BeginRequest;
            context.EndRequest += context_EndRequest;
        }

        void context_BeginRequest(object sender, EventArgs e) {
            var session = DependencyResolver.Current.GetService<ISession>();
            session.Transaction.Begin();
        }

        void context_EndRequest(object sender, EventArgs e) {
            var session = DependencyResolver.Current.GetService<ISession>();
            session.Transaction.Commit();
            session.Dispose(); 
        }

        public void Dispose() {}
    }
}
这是我注册会话的方式(使用StructureMap):
new Container(x => {

    x.Scan(a => {
        a.AssembliesFromApplicationBaseDirectory();
        a.WithDefaultConventions();
    });

    x.For<ISessionFactory>().Singleton().Use(...);
    x.For<ISession>().HybridHttpOrThreadLocalScoped().Use(sf => sf.GetInstance<ISessionFactory>().OpenSession());
    x.For<StringArrayType>().Use<StringArrayType>();

});
请记住,这是我已经尝试过的东西,并且发现它在我使用NHibernate的情况下效果很好。其他人可能有不同的意见(当然,这是受欢迎的)。     
好吧,我想您可以设置一个适合您在应用程序中执行的读取操作的事务级别,但问题是:是否真的需要在应用程序代码中执行该操作?我的猜测不是,除非您有一个用例不同于(n)休眠将通过配置应用的默认事务级别。 也许您可以在nhibernate配置中设置事务级别。 或者,探查器的设置有些过分热情?从这里无法分辨。 但是:您是否尝试过提交读事务?不应造成任何伤害。     
您正在将ISession传递到存储库的构造函数中,这很好。但这是我最喜欢的这门课。 仅保存通话会话。保存,因此不需要。 GetOrderHistory似乎正在按ID检索单个实体,为此您应使用“ 7”。您可以根据需要将结果放入集合中。 Commit方法不应位于存储库中。 要直接回答您的问题...   我该如何创建方法,而不必将每个方法都包装在一个   交易?我正在使用ninject   已经参加了我的会议,所以也许我可以   但是有时会利用   虽然我被迫做多次   单个请求中的交易。 我推荐的模式如下。这使用手动依赖项注入,但是您可以使用Ninject来解决依赖项。
List<OrderHistory> orderHistories;
var session = GetSession(); // Gets the active session for the request
var repository = new OrderHistory(Repository);
// new up more repositories as needed, they will all participate in the same transaction
using (var txn = session.BeginTransaction())
{
    // use try..catch block if desired
    orderHistories = repository.GetOrderHistories();
    txn.Commit();
}
  所以我不知道只有一个   每个请求的交易是一个灵魂。 一个会话中有多个事务非常好。我不喜欢等到请求结束提交,因为为时已晚,无法向用户提供良好的反馈。   我如何确保该对象   我要临时使用不要   意外得到承诺? 唯一确定的方法是使用IStatelessSession。不太确定的方法是从会话中逐出对象或清除会话。但是,建议不要使用NHibernate修改持久对象。   我如何在服务层中使用延迟加载。我不   想包围我的懒惰的东西   在交易中,因为通常使用   在我的服务层。 如果您使用的是每次请求会话,则应该不会有问题。但是您是对的,可以在事务之外进行延迟加载。我忽略了这些警告。我想您可以“触摸”所需的每个子对象,以便在事务中进行延迟加载,但我不会打扰。   我不想进行交易   我的服务层(这是   回购不是我的业务逻辑) 我不同意这一点。 UI或业务逻辑应管理事务。 UI是用户表达其意图(保存或取消我的更改)的地方,并且是管理交易的自然场所。     
推荐的方法是工作单元 (会话+交易)每个请求。 确保您可以使用NInject进行管理 会话生命周期,我写了博客 最近关于类似的方法 使用温莎城堡。 这是4个选项: 不要临时更改实体 在这种情况下使用无状态会话 分离物体时 做临时改变 回滚交易 我会选择第一个。 如果您使用的是每次请求会话模式,则不必担心延迟加载-它将在同一请求中执行并自动包装在事务中。     

要回复问题请先登录注册