NHibernate ISession.Save() - 为什么这会立即保留我的实体?

发布于 2024-11-17 00:27:38 字数 976 浏览 2 评论 0原文

我正在使用 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();
}

我的印象是 _context.Save() 行只是让 ISession 知道新实体,但在我通过 tx.Commit() 行刷新会话之前,不会将任何更改保留到数据库中。

但我观察到,每次我调用 _context.Save() 时,数据库都会获取一个新实体。结果,我对数据库进行了太多的单独调用。

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

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

可以找到有关身份生成器的一些有用信息 这里

I am creating a large number of entities with NHibernate, attaching them to my ISession, and then using a transaction to commit my changes to the database. Code sample is below:

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();
}

I was under the impression that the line _context.Save() simply makes the ISession aware of the new entity, but that no changes are persisted to the database until I Flush the session via the line tx.Commit().

What I've observed though, is that the database gets a new entity every time I call _context.Save(). I end up with too many individual calls to the database as a result.

Does anyone know why ISession.Save() is automatically persisting changes? Have I misunderstood something about how NHibernate behaves? Thanks.

***EDIT - Just to clarify (in light of the two suggested answers) - my problem here is that the database IS getting updated as soon as I call _context.Save(). I don't expect this to happen. I expect nothing to be inserted into the database until I call tx.Commit(). Neither of the two suggested answers so far helps with this unfortunately.

Some good information on identity generators can be found here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

故事↓在人 2024-11-24 00:27:38

尝试:

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();
}

Try:

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();
}
吃素的狼 2024-11-24 00:27:38

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

来自NHibernate POID 生成器揭晓

后插入生成器,如名称所示
建议,在之后分配 id
实体存储在数据库中。一个
执行 select 语句
数据库。它们有很多缺点,
我认为必须使用它们
仅适用于棕地项目。那些
我们不建议使用发电机
作为 NH 团队。

一些缺点是
正在关注

  1. 工作单元因使用而被破坏
    那些策略。没关系,如果
    您正在使用 FlushMode.Commit,每个
    将结果保存在插入语句中
    反对数据库。作为最佳实践,我们
    应该推迟插入到提交,
    但使用后插入生成器
    使其在保存时提交(这就是
    UoW 不这样做)。
  2. 这些策略
    取消批处理程序,你不能接受
    发送多个查询的优点
    立即(因为它必须立即进入数据库
    保存时间)

Which identity generator are you using? If you are using post-insert generators like MSSQL/MySQL's Identity or Oracle's sequence to generate the value of your Id fields, that is your problem.

From NHibernate POID Generators Revealed:

Post insert generators, as the name
suggest, assigns the id’s after the
entity is stored in the database. A
select statement is executed against
database. They have many drawbacks,
and in my opinion they must be used
only on brownfield projects. Those
generators are what WE DO NOT SUGGEST
as NH Team
.

Some of the drawbacks are the
following

  1. Unit Of Work is broken with the use of
    those strategies. It doesn’t matter if
    you’re using FlushMode.Commit, each
    Save results in an insert statement
    against DB. As a best practice, we
    should defer insertions to the commit,
    but using a post insert generator
    makes it commit on save (which is what
    UoW doesn’t do).
  2. Those strategies
    nullify batcher, you can’t take the
    advantage of sending multiple queries
    at once(as it must go to database at
    the time of Save)
云淡月浅 2024-11-24 00:27:38

您可以在配置中设置批量大小:

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

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

You can set your batch size in your configuration:

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

Or you can set it in code. And make sure you do your saves within a transaction scope.

稍尽春風 2024-11-24 00:27:38

尝试将 FlushMode 设置为 Commit:

ISession _context = SessionProvider.OpenSession();
context.FlushMode = FlushMode.Commit;

同行设置批量大小的建议也很好。

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

Try setting the FlushMode to Commit:

ISession _context = SessionProvider.OpenSession();
context.FlushMode = FlushMode.Commit;

peer's suggestion to set the batch size is good also.

My understanding is that when using database identity columns, NHibernate will defer inserts until the session is flushed unless it needs to perform the insert in order to retrieve a foreign key or ensure that a query returns the expected results.

以酷 2024-11-24 00:27:38

好吧,

  1. rebelliard 的答案是有可能的,具体取决于您的映射,
  2. 您没有使用显式事务(StuffHappens 的答案),
  3. 默认刷新模式是自动,这会使事情变得复杂(Jamie Ide 的答案),
  4. 如果通过任何更改,您使用 nhibernate api 进行任何查询默认行为是首先将缓存刷新到数据库,以便这些查询的结果将与会话实体表示相匹配。

Well

  1. rebelliard's answer is a possibility depending on your mapping
  2. you are not using explicit transactions (StuffHappens' answer)
  3. default flush mode is auto and that complicates things (Jamie Ide's answer)
  4. if by any change you make any queries using the nhibernate api the default behaviour is to flush the cache to the database first so that the results of those queries will match the session entity representation.
昵称有卵用 2024-11-24 00:27:38

怎么样:

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();

}

What about :

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();

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文