Is there a way to map a entity's primary key in NHibernate in a way that it can be assigned or native at the same time, and perform the insert and update actions through stored procedures? In this way, if the Id has the unassigned value, it will be generated natively at the stored procedure, and if it has a different value, it will persist the assigned value.
After some tests, I found that you can map the same column to the same property twice, one as Id generated natively, and other as a common property, but not updatable. The first one allows NHibernate to get the Id value form the database, and the second allows to pass the Id value to the database but only on insert, preventing an additional update on the same transaction due to the property modification after insert.
This is the Fluent NHibernate mapping:
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");
}
}
And the stored procedure:
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
Notice that the stored procedure always perform a select of the ID, even if it doesn't generated it, because due to the mapping, NHibernate always expect to retrieve the ID from the database.