代码之家  ›  专栏  ›  技术社区  ›  Will I Am

使用Fluent NHibernate进行交易和删除

  •  1
  • Will I Am  · 技术社区  · 16 年前

    我开始玩(流利的)nhibernate,我想知道是否有人可以帮助以下。我相信这是一个完全没有意义的问题。

    我想做:

       delete from TABX where name = 'abc'
    

    其中,表tabx定义为:

       ID int
       name varchar(32)
       ...
    

    我基于Internet示例构建代码:

     using (ITransaction transaction = session.BeginTransaction())
                    {
                        IQuery query = session.CreateQuery("FROM TABX WHERE name = :uid")
                            .SetString("uid", "abc");
                        session.Delete(query.List<Person>()[0]);
                        transaction.Commit();
                    }
    

    但遗憾的是,它生成了两个查询(一个选择一个删除)。我想在一个语句中完成这项工作,就像在我的原始SQL中一样。正确的方法是什么?

    此外,我注意到,在互联网上的大多数示例中,人们往往总是将所有查询都包装在事务中。为什么会这样?如果我只是一句话,那就太过分了。人们是倾向于不经意地剪切和粘贴,还是有其他原因呢?例如,在我上面的查询中,如果我管理它从两个查询到一个查询,我应该能够删除begin/commit事务,不是吗?

    如果重要的话,我正在使用PostgreSQL进行实验。

    3 回复  |  直到 16 年前
        1
  •  2
  •   Diego Mijelshon    16 年前

    您可以使用以下代码在一个步骤中进行删除:

    session.CreateQuery("DELETE TABX WHERE name = :uid")
           .SetString("uid", "abc")
           .ExecuteUpdate();
    

    但是,这样做可以避免事件侦听器调用(它只是映射到一个简单的SQL调用)、缓存更新等。

        2
  •  2
  •   Chris    16 年前

    您的第一个查询来自 query.List<Person>() .

    您的实际删除语句来自 session.Delete(...)

    通常,当您只处理一个对象时,您将使用load()或get()。

    Session.Load(type, id) 将为您创建对象,而不在数据库中查找它。但是,一旦您访问对象的某个属性,它就会给对象添加水合物。

    Session.Get(type, id) 将为您查找数据。

    就事务而言,这是一篇很好的文章,解释了为什么用事务包装所有NHibernate查询是好的。

    http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions

        3
  •  0
  •   David Hogue    16 年前

    在nhibernate中,我注意到使用两个查询(如您所见)进行删除是最常见的。我相信这是预期的行为。唯一能解决这个问题的方法就是使用缓存,然后如果第一个查询恰好在更早的时候运行,就可以从缓存中加载它。

    至于在事务中包装所有内容:在大多数数据库中,事务无论如何都是隐式的。显式事务只是保证数据不会在您的中间操作中被更改。