有没有办法在 NHibernate 中映射实体的主键,使其可以同时分配或原生,并通过存储过程执行插入和更新操作?这样,如果Id有未赋值的值,就会在存储过程中原生生成,如果有不同的值,就会持久化赋值。
问问题
985 次
2 回答
1
我认为您的 ID 生成听起来非常自定义,因此可以编写一个自定义生成器,然后可以在您的映射中使用它。
在此处查找有关如何实现自定义生成器的一些示例。
基本上它看起来像这样
public class FDPSequence : TableGenerator
{
private const Int32 SeedValue = 1048576;
public override object Generate(ISessionImplementor session, object obj)
{
int counter = Convert.ToInt32(base.Generate(session, obj));
return counter + SeedValue + 1;
}
}
在您的场景中,您可能希望在某些情况下使用 NativeGenerator 并在其他情况下调用 SP ......
于 2013-10-10T07:01:14.327 回答
0
经过一些测试,我发现您可以将同一列映射到同一属性两次,一次作为本地生成的 Id,另一次作为公共属性,但不可更新。第一个允许 NHibernate 从数据库中获取 Id 值,第二个允许将 Id 值传递给数据库,但仅在插入时,防止由于插入后属性修改而对同一事务进行额外更新。
这是 Fluent NHibernate 映射:
public class ItemMap : ClassMap<Item>
{
public ItemMap()
{
Schema("dbo");
Table("Item");
Id(x => x.IdItem, "idItem").UnsavedValue(0).GeneratedBy.Native();
Map(x => x.IdItem, "idItem").Not.Update();
Map(x => x.AnotherBoringField, "anotherBoringField");
SqlInsert("EXEC [dbo].[StpInsertItem] @idItem=@p0, @anotherBoringField=@p1");
}
}
和存储过程:
CREATE PROCEDURE [dbo].[StpInsertItem]
@idItem INT,
@anotherBoringField VARCHAR(10)
AS
BEGIN
IF (@idItem = 0)
BEGIN
SELECT @idItem = MAX(idItem) + 1 FROM [dbo].[Item];
END
INSERT INTO [PT].[TblDBItem] (idItem, anotherBoringField)
VALUES (@idItem, @anotherBoringField);
SELECT @idItem id;
END
GO
请注意,存储过程总是执行 ID 的选择,即使它没有生成它,因为由于映射,NHibernate 总是希望从数据库中检索 ID。
于 2013-10-10T21:32:50.393 回答