Хорошо, вот 2 способа. Самое простое может не включать NHibernate, так как вы используете SQL Server ... Вы можете просто создать триггер INSTEAD OF INSERT на своей таблице, например так:
CREATE TRIGGER tgINSCategory ON Category INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON
INSERT INTO Category (SiteID, Name, SortOrder)
SELECT SiteID, Name,
ISNULL((SELECT MAX(c.SortOrder)
FROM Category c INNER JOIN INSERTED i ON c.SiteID = i.SiteID), 0) + 1
FROM INSERTED
END
В этом первом сценарии вы просто привязали бы NHibernate к столбцу SortOrder как доступный только для чтения (просто добавьте .ReadOnly () в свойство SortOrder для карты класса nhibernate)
Второй способ - использовать встроенную функцию NHibernate, называемую перехватчиками. С помощью перехватчика вы можете запускать любой код, который вам нравится, как раз в то время, когда NHibernate обычно генерирует SQL для выполнения действия DML. Приведенная ниже автоматическая вставка информации о создании, но будет очень похожа на то, что вам нужно. IInsertLoggable - это пользовательский интерфейс, который просто перечисляет свойства / столбцы, представляющие интерес для перехвата.
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
public class InsertDefaults : EmptyInterceptor {
private const string CREATED_BY = "CreatedById";
private Hashtable GetInsertLoggablePropertyIndexes(string[] Properties) {
Hashtable result = new Hashtable();
for (int i = 0; i < Properties.Length; i++) {
if (Properties[i] == CREATED_BY) {
result.Add(CREATED_BY, i);
break;
}
}
return result;
}
public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types) {
if (entity is IInsertLoggable) {
Hashtable indexes = GetInsertLoggablePropertyIndexes(propertyNames);
state[(int)indexes[CREATED_BY]] = currentUser;
PropertyInfo createdByProp = entity.GetType().GetProperty(CREATED_BY);
if (createdByProp != null)
createdByProp.SetValue(entity, currentUser, null);
}
return base.OnSave(entity, id, state, propertyNames, types);
}
}
По моему мнению, такая классическая операция триггера, вероятно, должна существовать в базе данных, и я бы выбрал первый вариант ...