【问题标题】:Using NHibernate Identifier Identity Generator使用 NHibernate 标识符身份生成器
【发布时间】:2009-10-25 10:25:42
【问题描述】:

我在不止一个地方阅读过使用 NHibernate 的标识符作为 主键被认为是一种不好的做法,因为 id 是在服务器端生成的 因此我们需要来自服务器的关于生成的 id 的回复。 (我想我也看过 Ayende 的帖子说 ms-sql 服务器可能有问题 生成标识符,这可能会导致主键违规)

现在,假设我有一个非常简单的域模型:博客和帖子。每个博客都可以拥有的地方 许多帖子,每个帖子都属于完全一个博客(一对多关系) 但我们只保存帖子 -> 博客关系而不是博客 -> 帖子

现在假设我使用 NHibernate WITH Idenitifer Id Generation 这样我不使用级联,所以我在我的 c# 代码中有这样的内容:

SaveBlogInTransaction(blog1);
SavePostsInTransaction(blog1posts);


现在,我的问题是:如果插入只能在我的代码中的一个地方完成 (不存在并发问题),是否保证帖子与数据库中博客的连接有效?


我的意思是让我们看看 Posts 的表架构:
PostId、PostName、PostType、BlogId

是否保证 BlogId 有效?

注意:每个方法都作为一个事务工作,最后它会提交到数据库

【问题讨论】:

    标签: nhibernate nhibernate-mapping


    【解决方案1】:

    即使在您重新表述的问题中,帖子也将具有正确的博客 ID。 NHibernate 将在调用 Save 后立即在数据库中插入 Blog 行,并在那时使用 SCOPE_IDENTITY 检索生成的标识值。此 ID 值将存储在 Blog 对象中,可供以后创建的任何帖子使用。

    这就是为什么人们说基于身份的 ID 不是一个好的选择——NHibernate 必须立即执行 SQL 来插入行,这样才能获得正确的身份值。如果使用different identity generator,NHibernate 可以避免在事务提交之前执行 SQL 插入语句,因为不需要联系数据库来确定对象 ID 的值。

    【讨论】:

    • 我同意 Sean 的观点,使用另一个生成器策略将执行更有效的事务,因为 NHibernate 不需要查询数据库来获取插入的 id。
    【解决方案2】:

    我想问一些不同的问题。 假设我们有以下代码:


    SaveBlogInTransaction(blog1);
    SaveBlogInTransaction(blog2);
    SavePostsInTransaction(post1_a, post1_b, ...); // all the posts of blog1
    SavePostsInTransaction(post2_a, post2_b, ...); // all the posts of blog2

    是否保证 post1_a, post1_b, ... 帖子的 blogid = blog1id?
    是否保证 post2_a, post2_b, ... 帖子的 blogid = blog2id?

    我认为 SCOPE_IDENTITY() 不适合这里,因为我们首先插入 blog1, blog2 只有 blog1_posts 和 blog2_posts

    注意:我们在模型中有一对多的关系,但在数据库中我们只为每个帖子保存 它所属的博客的 id(我们没有 BlogPosts 表)

    【讨论】:

      【解决方案3】:

      这取决于您的映射。如果您已经映射了一对多关系,使得 Blog 有一个 BlogPosts 集合并且 BlogPost 有一个对 Blog 的引用,那么您可以创建一个 Blog,将 Posts 添加到它的 BlogPosts 集合中,然后只保存博客。 NHibernate 将首先插入博客记录,然后在子对象上设置外键,然后再持久化它们。这保证 BlogId 是有效的。

      我没有查看 NHibernate 源代码,但我确信它使用了插入后检索身份的最佳实践,可能是 SCOPE_IDENTITY。 This blog post 讨论了这三种方法。

      我不同意使用身份是一种不好的做法。它的主要问题是 NHibernate 可能会在调用 Flush 之前持久化对象以检索身份。因此插入可能发生在事务之外,必须手动删除记录。

      【讨论】:

      • 我不需要 BlogPosts 表,因为我只为每篇文章保存它所连接的博客。我在域模型中有一对多关系,但在数据库中没有……我问是否可以保证数据库中的帖子条目将具有有效的 blogid(如果我们没有,则不为 NULL从服务器获取响应,之前插入的博客的 id 是什么)
      • BlogId 是如何生成的?我不确定我是否理解你的问题,但我认为答案是“不”。如果您在数据库中没有 FK 关系,则无法保证有效的 BlogId。
      • 我有一个外键。我实际上使用城堡活动记录。在 Post 类中,我有一个 Blog 类型的属性(但在 blog 类中,我没有提到帖子......)。现在看看我重新提出问题的方式,当我第一次插入多个博客时,然后才插入所有帖子。可以吗?我认为 SCOPE_IDENTITY 不应该在这里使用,因为我插入的博客不止一个。与每个帖子相关的 blogid 是否有可能出现错误?
      猜你喜欢
      • 2011-09-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 2010-09-19
      • 2016-09-09
      • 2013-08-01
      • 1970-01-01
      • 2017-10-29
      相关资源
      最近更新 更多