我有一个相当简单的表格,其中包含适当的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个元素,并且只有一个程序对表进行写访问(是的,我们真的知道这一点并且可以肯定!)但是还有另一种方法吗?或者(外部)数据库设计师做错了什么?
答案 0 :(得分:2)
我将此作为答案发布,因为它很长。
原来这个问题完全不同了。我在我的测试数据库上遇到了这个问题。我在我的开发系统上运行数据库的副本以进行集成测试。每次测试运行后,数据库都会被清除并重置为我从第三方收到数据时所处的状态。
在那个重置过程中,我有这个小家伙:
EXEC sp_MSForEachTable "DBCC CHECKIDENT ( '?', RESEED, 0)"
这会将每个标识列的种子设置为0,因此尝试插入新记录会导致错误。 D'哦!
我现在改为使用每个表的正确值,分别发出DBCC CHECKIDENT
命令,问题就消失了。
头 - &gt;桌子 - &gt;砰...