流畅的NHibernate:“不能在对象中插入重复的键”,即使Id是GeneratedBy.Native()或Identity()

时间:2018-01-31 08:42:51

标签: c# sql-server nhibernate fluent-nhibernate

我有一个相当简单的表格,其中包含适当的Fluent NHibernate映射:

public class Blurb {

    public virtual byte SimpleId { get; set; }
    public virtual string Foo { get; set; }
    public virtual string Bar { get; set; }
}

public class BlurbMap: ClassMap<Blurb> {

    public BlurbMap() {
        Id(x => x.SimpleId).Column("PK_SimpleID").GeneratedBy.Identity();
        Map(x => x.Foo);
        Map(x => x.Bar);
        Table("dbo.SimpleTable");
    }
}

请不要判断我使用byte作为ID,数据库是由第三方预先制作的,我无法更改。

我现在想插入一些东西,所以我这样做:

var blurb = new Blurb {
    Foo = "foo",
    Bar = "bar"
};

using(var txn = session.BeginTransaction()) {
    session.SaveOrUpdate(blurb); // <- boom!
    txn.Commit();
}

在我写“繁荣”的地方,我得到了例外:

could not insert: [Foo.Bar.Blurb][SQL: INSERT INTO dbo.SimpleTable (Foo, Bar) VALUES (?, ?); select SCOPE_IDENTITY()] ---> System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'PK_SimpleID'. Cannot insert duplicate key in object 'dbo.SimpleTable'. The duplicate key value is (1).

我再次使用SSMS尝试插入,我得到了相同的错误,但随后执行查询,错误消息改变如下:

The duplicate key value is (1)
The duplicate key value is (2)
The duplicate key value is (3)
...

直到插入成功时按下未使用的键。

我已经尝试GeneratedBy.Native()无济于事。目前,我只能想到像

这样的解决方法
var lastBlurb = session.Query<Blurb>().Select(x => x.SimpleId).Max();
newBlurb.SimpleId = lastBlurb + 1;
session.SaveOrUpdate(newBlurb);

这是可行的,因为“真正的”表只包含10到20个元素,并且只有一个程序对表进行写访问(是的,我们真的知道这一点并且可以肯定!)但是还有另一种方法吗?或者(外部)数据库设计师做错了什么?

1 个答案:

答案 0 :(得分:2)

我将此作为答案发布,因为它很长。

原来这个问题完全不同了。我在我的测试数据库上遇到了这个问题。我在我的开发系统上运行数据库的副本以进行集成测试。每次测试运行后,数据库都会被清除并重置为我从第三方收到数据时所处的状态。

在那个重置过程中,我有这个小家伙:

EXEC sp_MSForEachTable "DBCC CHECKIDENT ( '?', RESEED, 0)"

这会将每个标识列的种子设置为0,因此尝试插入新记录会导致错误。 D'哦!

我现在改为使用每个表的正确值,分别发出DBCC CHECKIDENT命令,问题就消失了。

头 - &gt;桌子 - &gt;砰...