NHibernate ISession.Save() - 为什么这会立即持续存在于我的实体中?

JMc*_*JMc 4 nhibernate transactions isession

我正在使用NHibernate创建大量实体,将它们附加到我的ISession,然后使用事务将我的更改提交到数据库.代码示例如下:

ISession _context = SessionProvider.OpenSession();

//Create new entities
for(int i=0; i<100; i++)
{
    MyEntity entity = new MyEntity(i);

    //Attach new entity to the context
    _context.Save(entity);
}

//Persist all changes to the database
using(var tx = _context.BeginTransaction())
{
    //Flush the session
    tx.Commit();
}
Run Code Online (Sandbox Code Playgroud)

我的印象是_context.Save()行只是让ISession知道新实体,但是在我通过tx.Commit()行刷新会话之前,没有任何更改持久存储到数据库.

我观察到的是,每次调用_context.Save()时数据库都会获得一个新实体.因此,我最终会对数据库进行过多的单独调用.

有谁知道为什么ISession.Save()会自动持久更改?我是否误解了NHibernate的行为方式?谢谢.

***编辑 - 只是为了澄清(根据两个建议的答案) - 我的问题是,一旦我调用_context.Save(),数据库就会更新.我不指望这会发生.我希望在调用tx.Commit()之前不要将任何内容插入到数据库中.到目前为止,两个建议的答案都没有帮助解决这个问题.

可在此处找到有关身份生成器的一些有用信息

Stu*_*ens 7

尝试:

using(Session _context = SessionProvider.OpenSession())
using(var tx = _context.BeginTransaction())
{
    //Create new entities
    for(int i=0; i<100; i++)
    {
        MyEntity entity = new MyEntity(i);

        //Attach new entity to the context
        _context.Save(entity);
    }

    //Flush the session
    tx.Commit();
}
Run Code Online (Sandbox Code Playgroud)


reb*_*ard 6

你使用哪个身份生成器?如果您使用后插入生成器(如MSSQL/MySQL Identity或Oracle)sequence来生成Id字段的值,那就是您的问题.

来自NHibernate的POID生成器显示:

顾名思义,后插入生成器在实体存储在数据库中后分配id.对数据库执行select语句.它们有许多缺点,在我看来它们只能用于棕色地带项目.那些发电机是我们不建议的NH团队.

一些缺点如下

  1. 使用这些策略打破了工作单元.如果你使用FlushMode.Commit没关系,每个Save都会产生一个针对DB的插入语句.作为最佳实践,我们应该将插入延迟到提交,但是使用post insert生成器使它在save上提交(这是UoW不会做的).
  2. 这些策略使batcher无效,你不能利用一次发送多个查询(因为它必须在保存时转到数据库)