Я долго размышлял над этим сценарием и перепробовал несколько вещей.
Прежде всего, я не очень люблю хранимые процедуры, зачем использовать NHibernate, если вы хотите привязать себя к конкретному движку БД, говорю я. В этом сценарии хранимые процессы (вариант 2) могут вести себя очень похоже на параметры 1 и 3, в зависимости от реализации процесса (т. Е. Запрашивает ли он сначала, а затем сохраняет, или выполняет более сложную транзакцию с откатом). Так что, если вы не имеете в виду что-то еще, я не буду комментировать дальше.
Вы можете использовать вариант 1, но это требует больше работы от вас как программиста. Это может быть хорошо для 1-2 сущностей, но можете ли вы обобщить это для всех ваших сущностей, неизвестно, так как я не знаю деталей вашего проекта. Кроме того, зачем делать запросы, если NHibernate может сделать это для вас?
Поэтому я бы порекомендовал вариант 3, я предпочитаю его, и он очень хорошо работает для меня.
Когда соблюдается ограничение, я откатываю всю транзакцию. Я также удостоверился, что получил нарушающий элемент, поэтому я могу сказать пользователю что-то «умное», например: «Пользователь x не может быть сохранен, потому что электронная почта y является дубликатом», а не «Пользователь x не может быть сохранен: повторяющаяся запись».