NHibernate ISession.Save()-为什么会立即持久化我的实体?

NHibernate ISession.Save()-为什么会立即持久化我的实体?,nhibernate,transactions,isession,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 _c

我正在使用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();
}
ISession\u context=SessionProvider.OpenSession();
//创建新实体
对于(int i=0;i尝试:

使用(会话_context=SessionProvider.OpenSession())
使用(var tx=_context.BeginTransaction())
{
//创建新实体
对于(inti=0;i

ISession _context = SessionProvider.OpenSession();

//Persist all changes to the database
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();

}
ISession\u context=SessionProvider.OpenSession();
//保留对数据库的所有更改
使用(var tx=_context.BeginTransaction())
{
//创建新实体

对于(int i=0;i您使用的是哪个标识生成器?如果您使用MSSQL/MySQL的
identity
或Oracle的
sequence
等插入后生成器来生成Id字段的值,这就是您的问题

发件人:

Post insert生成器,如名称所示 建议,在 实体存储在数据库中 对执行select语句 数据库。它们有很多缺点, 在我看来,它们必须被使用 只在棕地项目上。那些 发电机是我们不建议的 作为NH团队

一些缺点是 跟随

  • 工作单元因使用 那些策略,如果 您正在使用FlushMode。提交,每个 将结果保存在insert语句中 针对DB。作为最佳实践,我们 应将插入延迟到提交, 但是使用插入后生成器 使其在保存时提交(这是什么 UoW不这样做)
  • 这些战略 取消批处理程序,您不能接受 发送多个查询的优点 立即(因为它必须在 保存时间)

  • 您可以在配置中设置批处理大小:

    <add key="hibernate.batch_size" value="10" /> 
    
    
    

    或者您可以在代码中进行设置。并确保在事务范围内进行保存。

    尝试将FlushMode设置为提交:

    ISession _context = SessionProvider.OpenSession();
    context.FlushMode = FlushMode.Commit;
    
    同行关于设置批量大小的建议也很好

    我的理解是,在使用数据库标识列时,NHibernate将推迟插入,直到刷新会话,除非它需要执行插入以检索外键或确保查询返回预期结果。

  • Rebeliard的答案可能取决于你的地图
  • 您没有使用显式事务(StuffOccurs的回答)
  • 默认的刷新模式是自动的,这会使事情复杂化(JamieIDE的答案)
  • 如果通过任何更改使用nhibernate api进行任何查询,默认行为是首先将缓存刷新到数据库,以便这些查询的结果与会话实体表示相匹配

  • 我认为这实际上可能是问题所在。我目前有:在我的配置文件中设置。今晚我将进行测试,并将其标记为答案,如果这是问题所在。谢谢!我一直在使用标识作为Id生成器,这似乎是我问题的原因。我现在正在寻找工作单元/存储库模式的合适替代方案,在这里我想明确首先将多个实体与ISession关联后,我自己刷新会话。谢谢。这是预期的行为,
    保存
    事务
    之外执行。正确答案应该是@StuffOccessdown@THBBFT,在事务之外不会导致保存发送到数据库。StuffOccess没有给出正确的答案,说明为什么它会在
    Save
    调用中插入。这个答案只是为了确保插入被回滚,但这不是OP关注的问题。它的编辑进一步证实了这一点。尝试将其置于顶部。
    ISession _context = SessionProvider.OpenSession();
    context.FlushMode = FlushMode.Commit;