Я заменил специализацию шаблона функции специализацией структур, и мой код работает нормально Посмотрите на следующий код.
// This file is a "Hello, world!" in C++ language by GCC for wandbox.
#include <iostream>
#include <string>
template<typename T>
concept Hashtable = requires(T a) {
{ std::hash<T>{}(a) } -> std::size_t;
};
struct Foo {};
template <typename T>
struct Boo {
static constexpr char value[] = "Type T is not a hashtable";
};
template <Hashtable HashT>
struct Boo<HashT> {
static constexpr char value[] = "Type T is a hashtable";
};
template <typename T>
void Bar() {
std::cout << Boo<T>::value << std::endl;
}
int main()
{
Bar<int>();
Bar<Foo>();
}
Нет никакой опции указать порядок операций в транзакции, поскольку он трудно кодируется следующим образом (из документации):
SQL-операторы выпущены в следующем порядке
- все вставки объекта, в том же порядке соответствующие объекты были сохранены с помощью ISession. Сохраните ()
- все обновления объекта
- все удаления набора
- все удаления элемента набора, обновления и вставки
- все вставки набора
- все удаления объекта, в том же порядке соответствующие объекты были удалены с помощью ISession. Удалите ()
(Исключение - то, что объекты с помощью собственного идентификационного поколения вставляются, когда они сохраняются.)
По сути, я могу бросить вызов Вам отвечать, почему Вы добавляете новый объект с существующим идентификатором? Идентификатор, как предполагается, уникален для определенного "объекта". Если бы того объекта не стало, то так должен быть его идентификатор.
Другая опция состояла бы в том, чтобы сделать обновление на той записи вместо удаления/вставления. Это сохраняет идентификатор тем же, таким образом, нет никакого нарушения ограничения на уникальность данных (на ключе, по крайней мере), и можно изменить все другие данные так, чтобы это была "новая" запись.
Править: Так, по-видимому, я не был полностью уделением внимания вопросу, когда я ответил, так как это - проблема с ограничением на уникальность данных на столбец непервичного ключа.
Я думаю, что у Вас есть два решения выбрать из:
Session.Flush()
после Вашего удалять, который выполнит все изменения в сессии до той точки, после которой можно продолжить остальных (вставка нового объекта). Это работает в транзакции также, таким образом, Вы не должны волноваться об атомарности.ReplacePage
функция, которая обновляет существующий объект с новыми данными, но сохраняет первичный ключ и уникальный столбец тем же.У меня такая же проблема ... У меня есть объект, у которого есть коллекция, которая сопоставлена с таблицей, содержащей уникальное ограничение.
Я не понимаю, что, согласно ответу Стюарта, удаление коллекции должно происходить до вставки коллекции?
Когда я погружаюсь в исходный код NHibernate, я нахожу класс CollectionUpdateAction
, который содержит этот код в своем методе Execute
:
persister.DeleteRows(collection, id, session);
persister.UpdateRows(collection, id, session);
persister.InsertRows(collection, id, session);
Тогда я предполагаю, что удаления выполняются перед вставками, но, видимо, это не так. Is the CollectionUpdateAction not used in this scenario? When is the CollectionUpdateAction used?
I have worked around this like this:
All my database access goes via a repository; in the save method of my repository, I have this code for my entity:
public void Save( Order orderObj )
{
// Only starts a transaction when there is no transaction
// associated yet with the session
With.Transaction(session, delegate()
{
session.SaveOrUpdate (orderObj);
session.Flush();
foreach( OrderLine line in orderObj.Lines )
{
session.SaveOrUpdate (line);
}
};
}
Итак, я сохраняю orderObj, и, поскольку для каскада установлено значение delete-orphan, объекты, которые необходимо удалить, будут удалены из базы данных.
После того, как я вызываю SaveOrUpdate
, я должен убедиться, что внесены изменения в базу данных.
Поскольку параметр каскада удаления-сироты гарантирует, что никакие строки заказа не вставляются и не обновляются, мне приходится перебирать мою коллекцию и вызывать 'SaveOrUpdate' для каждой строки заказа. Это гарантирует, что новые OrderLines будут вставлены, а измененные обновлены. Никакие действия не будут выполнены для OrderLines, которые не изменились.
Хотя это не идеальное решение (это уродливый взлом, IMHO), это вроде работает, и оно абстрагируется за репозиторием, так что я так и поступаю с этой проблемой пока ...