Принуждение NHibernate к каскадному удалению прежде вставляет

Я заменил специализацию шаблона функции специализацией структур, и мой код работает нормально Посмотрите на следующий код.

// 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>();
}
22
задан Peter Mortensen 9 November 2010 в 17:23
поделиться

2 ответа

Нет никакой опции указать порядок операций в транзакции, поскольку он трудно кодируется следующим образом (из документации):

SQL-операторы выпущены в следующем порядке

  • все вставки объекта, в том же порядке соответствующие объекты были сохранены с помощью ISession. Сохраните ()
  • все обновления объекта
  • все удаления набора
  • все удаления элемента набора, обновления и вставки
  • все вставки набора
  • все удаления объекта, в том же порядке соответствующие объекты были удалены с помощью ISession. Удалите ()

(Исключение - то, что объекты с помощью собственного идентификационного поколения вставляются, когда они сохраняются.)

По сути, я могу бросить вызов Вам отвечать, почему Вы добавляете новый объект с существующим идентификатором? Идентификатор, как предполагается, уникален для определенного "объекта". Если бы того объекта не стало, то так должен быть его идентификатор.

Другая опция состояла бы в том, чтобы сделать обновление на той записи вместо удаления/вставления. Это сохраняет идентификатор тем же, таким образом, нет никакого нарушения ограничения на уникальность данных (на ключе, по крайней мере), и можно изменить все другие данные так, чтобы это была "новая" запись.

Править: Так, по-видимому, я не был полностью уделением внимания вопросу, когда я ответил, так как это - проблема с ограничением на уникальность данных на столбец непервичного ключа.

Я думаю, что у Вас есть два решения выбрать из:

  1. Звонить Session.Flush() после Вашего удалять, который выполнит все изменения в сессии до той точки, после которой можно продолжить остальных (вставка нового объекта). Это работает в транзакции также, таким образом, Вы не должны волноваться об атомарности.
  2. Создайте a ReplacePage функция, которая обновляет существующий объект с новыми данными, но сохраняет первичный ключ и уникальный столбец тем же.
30
ответ дан 29 November 2019 в 05:07
поделиться

У меня такая же проблема ... У меня есть объект, у которого есть коллекция, которая сопоставлена ​​с таблицей, содержащей уникальное ограничение.

Я не понимаю, что, согласно ответу Стюарта, удаление коллекции должно происходить до вставки коллекции? Когда я погружаюсь в исходный код 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?

Answer:

I have worked around this like this:

  • In my mapping, I've set the cascade option to 'delete-orphan' instead of 'all-delete-orphan'
  • 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), это вроде работает, и оно абстрагируется за репозиторием, так что я так и поступаю с этой проблемой пока ...

4
ответ дан 29 November 2019 в 05:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: