2010-05-19 91 views
1

我开始玩(流利)nHibernate,我想知道如果有人可以帮助以下。我相信这是一个总问题。交易和删除使用流利nhibernate

我想做的事:

delete from TABX where name = 'abc' 

其中表TABX被定义为:

ID int 
    name varchar(32) 
    ... 

我建立一个基于互联网的样本代码:

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中一样。这样做的正确方法是什么?

此外,我注意到,在互联网上的大多数样本中,人们往往总是将所有查询包含在交易中。这是为什么?如果我只运行一个单一的陈述,那似乎是一种矫枉过正。人们倾向于无意识地剪切和粘贴,还是有其他原因?例如,在我上面的查询中,如果我确实管理它从两个查询中获得它,我应该能够删除开始/提交事务,不是吗?

如果它很重要,我使用PostgreSQL进行实验。

+1

从技术上讲,你并没有真正在你的代码中使用fluent-nhibernate。流利的nHibernate是你用来生成映射文件的东西。 – 2010-05-19 23:32:44

回答

2

你可以在一个步骤下面的代码删除:

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

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

+0

避免事件监听器调用的含义是什么? – 2010-05-20 00:30:22

+0

如果你不用它们做任何事情,什么都不要。最常见的用法是更改审计。 – 2010-05-20 01:30:24

0

在NHibernate中,我已经注意到最常见的是用你看到的两个查询来删除它。我相信这是预期的行为。解决这个问题的唯一方法就是使用缓存,如果碰巧早点运行,那么可以从缓存中加载第一个查询。至于包含事务中的所有内容:在大多数数据库中,无论如何对于每个查询都隐含事务。明确的交易只是保证数据不会在您的操作中被更改。

2

您的第一个疑问来自于query.List<Person>()

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

通常,当你面对的只有一个对象,你会使用load()或获得()。

Session.Load(type, id)将为您创建对象,而无需在数据库中查找它。但是,只要访问其中一个对象的属性,它就会保湿对象。

Session.Get(type, id)实际上会为您查找数据。

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

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

+0

谢谢。这听起来有点违反直觉来人手工制作SQL代码(我仍然习惯做存储过程)。 – 2010-05-20 02:30:36

+0

我知道你的意思。在学习nHibernate时,我的口头禅是“没有数据库”。我只需要专注于处理对象和关系,而不是表和外键。但是,同样,您仍然可以使用一个数据库调用进行删除。只需在Load()返回的对象上使用Session.Load()和Session.Delete()即可。 – 2010-05-20 03:54:40