powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
32 сообщений из 32, показаны все 2 страниц
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710245
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем доброго времени суток. Пишу тестовый пример, который был бы способен удалять данные с помощью NHibernate.

Классы:
Код: plaintext
1.
2.
3.
4.
public class Book
{
    public virtual string Name { get; set; }
    public virtual Color Color { get; set; }
}

Код: plaintext
1.
2.
3.
4.
public class Color
{
    public virtual string Name { get; set; }
    public virtual IList<Book> Books { get; set; }
}

Маппинги:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NHPoligon" assembly="NHPoligon" default-lazy="false">

  <class name="Book" table="books" >
    <id column="Id" type="int">
      <generator class="native"/>
    </id>

    <property name="Name" type="string" column="name"/>

    <many-to-one name="Color" class="Color" cascade="all-delete-orphan"  >
      <column name="idColor"/>
    </many-to-one>

  </class>
  
</hibernate-mapping>

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NHPoligon" assembly="NHPoligon" default-lazy="false">

  <class name="Color" table="colors">

    <id column="Id" type="int">
      <generator class="native"/>
    </id>

    <property name="Name" type="string" column="name"/>

    <bag name="Books" inverse="true">
      <key column="Id"/>
      <one-to-many class="Book"/>  
    </bag>
    
  </class>

</hibernate-mapping>


В базе данных завел две книги, ссылающихся на один цвет (FirstBook и SecondBook ссылаются на цвет Orange)

Теперь, в отдельной сессии, делаю так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
using (NHibernate.ISession session = SessionManager.OpenSession())
{
    Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();
    
    session.Delete(book);

    session.Flush();
}

При этом появляется исключение:

The DELETE statement conflicted with the REFERENCE constraint \"FK_books_colors\". The conflict occurred in database \"NHPoligon\", table \"dbo.books\", column 'idColor'.\r\nThe statement has been terminated.

То есть, NHibernate видит каскад, и пытается выполнить два оператора Delete на базе данных:
Код: plaintext
1.
NHibernate: DELETE FROM books WHERE Id = @p0;@p0 = 26
NHibernate: DELETE FROM colors WHERE Id = @p0;@p0 = 10

в то время, когда на удаляемый color есть ссылка из другого объекта Book, который в этой сессии не подгружен => NHibernate о нем не знает.

Вопрос: Можно-ли заставить NHibernate автоматически проверять, существуют ли ссылки на цвета из других книг, чтобы не удалять такие цвета при удалении книги?

P.S. Такая же ситуация (с тем же самым exception) случалась и с "многие-ко-многним".

Заранее спасибо.
Заранее спасибо.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710353
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pregamil,

он перед удаление залазит в базу за удаляемыми книгами по цвету, причем тут другая сессия.
то есть он берет самые свежие данные повсем книгам выбранного цвета.. подгружена не подгружена, это он сам решает что делать.
зы или я опять что не понял..
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710379
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Тогда немного разъясню.

Как писал выше, в базе данных имеется две книжки, ссылающиеся на один цвет.

Сначала выполняется запрос для выбора одной из двух имеющихся в базе книг:

Код: plaintext
Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();

При этом на базу идут запросы:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
SELECT this_.Id as Id0_1_, 
       this_.name as name0_1_, 
       this_.idColor as idColor0_1_, 
       color2_.Id as Id1_0_, 
       color2_.name as name1_0_ 
FROM books this_ 
left outer join colors color2_ on this_.idColor=color2_.Id 
WHERE this_.name = @p0;@p0 = 'First book'


SELECT books0_.Id as Id2_, 
       books0_.Id as Id0_1_, 
       books0_.name as name0_1_, 
       books0_.idColor as idColor0_1_, 
       color1_.Id as Id1_0_, 
       color1_.name as name1_0_ 
FROM books books0_ 
left outer join colors color1_ on books0_.idColor=color1_.Id 
WHERE books0_.Id=@p0;@p0 =  10 

Потом я пытаюсь удалить эту книжку:

Код: plaintext
1.
session.Delete(book);
session.Flush();

При этом на базу идут запросы:

Код: plaintext
1.
DELETE FROM books WHERE Id = @p0;@p0 =  30 
DELETE FROM colors WHERE Id = @p0;@p0 =  10 

И тут же программа вылетает с исключением:

The DELETE statement conflicted with the REFERENCE constraint \"FK_books_colors\". The conflict occurred in database \"NHPoligon\", table \"dbo.books\", column 'idColor'.\r\nThe statement has been terminated.

То есть NHibernate не проверил, есть ли еще книги, ссылающиеся на удаляемый цвет, и попытался удалить эту книжку вместе с цветом. А это нарушает целостность данных. Вопрос в том, есть ли способ заставить эту ОРМ делать проверки перед удалением?
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710427
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pregamil,

вот второй запрос и есть все книги, которые имеют этот цвет.
сделайте вот что.
уберите из мапа default-lazy="false" отовсюду, отсутствие ленивости и джойны всю картину смазывают.
да насилие над базой.
закомментируйте делите и и флеш, уберите отладку, и сделайте прогон.
на базу пойдет один запрос селект, на выбор вашей книги.
ну типа select * from book where name=`First book`
потом раскоментируйте строки и сделайте прогон с удалением.
к первоначальному селекту
добавится селект на выбор колора.
select * from color where id=10
потом хибер должен вытащить все книги
с этим цветом
(вдруг ваша другая сессия что добавила.)
select * from book where colorID=10;
а потом удалять.сначало книжки а потом солор
вот так должно быть согласно вашему мапу.
может вы этого хотели?
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710530
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Убрал default-lazy

Маппинги:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NHPoligon" assembly="NHPoligon">

  <class name="Color" table="colors">

    <id column="Id" type="int">
      <generator class="native"/>
    </id>

    <property name="Name" type="string" column="name"/>

    <bag name="Books" inverse="true">
      <key column="Id"/>
      <one-to-many class="Book"/>  
    </bag>
    
  </class>

</hibernate-mapping>

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NHPoligon" assembly="NHPoligon">

  <class name="Book" table="books" >
    <id column="Id" type="int">
      <generator class="native"/>
    </id>

    <property name="Name" type="string" column="name"/>

    <many-to-one name="Color" class="Color" cascade="all-delete-orphan"  >
      <column name="idColor"/>
    </many-to-one>

  </class>
  
</hibernate-mapping>

Шаг1

Код: plaintext
1.
Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();

Код: plaintext
1.
2.
3.
4.
SELECT this_.Id as Id0_0_, 
           this_.name as name0_0_, 
           this_.idColor as idColor0_0_ 
FROM books this_ 
WHERE this_.name = @p0;@p0 = 'First book'

Шаг 2

Код: plaintext
session.Delete(book);

Код: plaintext
1.
2.
3.
SELECT color0_.Id as Id1_0_, 
           color0_.name as name1_0_ 
FROM colors color0_ 
WHERE color0_.Id=@p0;@p0 =  10 

Шаг 3

Код: plaintext
session.Flush();

Код: plaintext
1.
DELETE FROM books WHERE Id = @p0;@p0 =  32 
DELETE FROM colors WHERE Id = @p0;@p0 =  10 

Код: plaintext
1.
2.
3.
4.
5.
NHibernate.Exceptions.GenericADOException was unhandled
  Message="could not delete: [NHPoligon.Color#10][SQL: DELETE FROM colors WHERE Id = ?]"
  Source="NHibernate"
  SqlString="DELETE FROM colors WHERE Id = ?"
Message="The DELETE statement conflicted with the REFERENCE constraint \"FK_books_colors\". The conflict 
occurred in database \"NHPoligon\", table \"dbo.books\", column 'idColor'.\r\nThe statement has been terminated."

==================

Исключение снова появляется, так как NHibernate снова пытается удалить Color, на который всё еще есть ссылающиеся книжки...

Мне нужно, чтобы ORM проверяла, если есть еще другие ссылающиеся на цвет книжки, то не трогала цвет. Если ссылающихся на цвет книжек больше нет, то удаляла этот цвет.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710533
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Где-то в степипотом хибер должен вытащить все книги с этим цветом (вдруг ваша другая сессия что добавила.)
select * from book where colorID=10;
По сути, этого и не хватает... А в идеале хотелось бы TSQL-проверки IF EXISTS , но сомневаюсь, что с NHibernate такое является возможным. Уже хотябы первым способом, но чтобы работало...
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710847
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Насколько я знаю, NHibernate не будет рекурсивно искать зависимости между объектами. (В случае многие ко многим представляете во что это выльется? Truncate table быстрее и проще.)
Моё мнение - у вас ошибка в проектировании. Определитесь с объектом, который будет отвечать за время жизни своих составляющих. Гради Буч неплохо раскрывал эту тему в книге по ОО анализу и проектированию.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710929
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtorМоё мнение - у вас ошибка в проектировании. Определитесь с объектом, который будет отвечать за время жизни своих составляющих. Гради Буч неплохо раскрывал эту тему в книге по ОО анализу и проектированию.
На счет ошибки в проектировании - у меня ассоциация типа aggregation, не composition, то есть время жизни цвета совсем не равно времени жизни книжки. А ОРМ, думаю, должна уметь распознать такие вещи и не допускать REFERENCE-constraint конфликтов.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710940
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если время жизни цвета не равно времени жизни книжки - то цвет не должен удалятся при удалении книжки. Каскадное удаление там лишнее.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710971
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtorЕсли время жизни цвета не равно времени жизни книжки - то цвет не должен удалятся при удалении книжки. Каскадное удаление там лишнее.
Хорошо. Как тогда удалять цвета, на которые больше не осталось ссылок с книжек? На сколько я понимаю, этим занимается all-delete-orhpan? Или его нужно ставить на сторону цвета, а не книжки?
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36710987
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В цвета и книжки нужно удалять отдельно. Для цветов, по которым книжек не осталось, можно HQL применить.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711033
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Стало быть, если каскадом можно удалять только под-объекты с меньшим либо равным временем жизни, чем у агрегирующего их объекта, то зачем придумали all-delete-orphan? Ведь в этом случае одиночек быть не может, все "вложенные" объекты и так будут удаляться. А если время жизни разное, то, по этой логике, каскад применять нельзя...

И еще, как же тогда с этим?
Где-то в степи потом хибер должен вытащить все книги с этим цветом (вдруг ваша другая сессия что добавила.)
select * from book where colorID=10;
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711078
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ответ на ваш вопрос есть в документации, пункт 9.9 и 19 .

Насчёт топика Где-то в степи, я у меня есть сомнения, что он отражает реальное поведение NHibernate. Да, если выключить lazy - то граф объектов хибер действительно загрузит полностью. Но это не значит, что при удалении одного объекта он будет удалять остальные.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711104
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Большое спасибо, очень помогли!

Ключевые идеи:
NHibernate documentationLikewise, to delete all objects in a graph, either
* Delete() each individual object OR
* map associated objects using cascade="all", cascade="all-delete-orphan" or cascade="delete".
Recommendation:
* If the child object's lifespan is bounded by the lifespan of the of the parent object make it a lifecycle object by specifying cascade="all".
* Otherwise, Save() and Delete() it explicitly from application code. If you really want to save yourself some extra typing, use cascade="save-update" and explicit Delete().
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711119
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я бы еще заострил внимание на отличии cascade="all" и cascade="all-delete-orphan":
NHibernate documentationIf a transient child is dereferenced by a persistent parent, nothing special happens (the application should explicitly delete the child if necessary) unless cascade="all-delete-orphan", in which case the "orphaned" child is deleted.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711184
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
NHibernate documentstionIf a transient child is dereferenced by a persistent parent, nothing special happens (the application should explicitly delete the child if necessary) unless cascade="all-delete-orphan", in which case the "orphaned" child is deleted.
А здесь не понятно. Как я понял: если несохраненный ранее в базу child был удален из коллекции объекта parent, то при выставленном cascade="all-delete-orphan" NHibernate будет удалять из базы заведомо несохраненный child?
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711221
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне тоже кажется, что слово transient там лишнее. Наверно описка вышла. Чуть выше есть более точное выражение:
NHibernate documentationMapping an association (many-to-one, or collection) with cascade="all" marks the association as a parent/child style relationship where save/update/deletion of the parent results in save/update/deletion of the child(ren). Futhermore, a mere reference to a child from a persistent parent will result in save / update of the child. The metaphor is incomplete, however. A child which becomes unreferenced by its parent is not automatically deleted, except in the case of a <one-to-many> association mapped with cascade="all-delete-orphan".
И далее в примере п. 19.3 про transient тоже ни слова.
Поэтому будем считать, что если Parent более не ссылается на Child, то в случае cascade="all" Child не будет удалён из базы, а в случае cascade="all-delete-orphan" - будет удалён.

Специально проверять сейчас лениво. :)
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711264
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А я проверил :)

Код: plaintext
<many-to-one name="Color" class="Color" cascade="all-delete-orphan">

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
using (NHibernate.ISession session = SessionManager.OpenSession())
{
    Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();

    //Меняю цвет на новый, а старый остается без владельца
    book.Color = new Color() { Name = "Фиолетовый" };
    book.Color.Books.Add(book);

    session.Save(book);
    session.Flush();
}

При этом прошлый цвет, завязанный на одну только книгу, не удалился, несмотря на то, что ссылающихся на этот цвет книг больше не осталось. Пробовал каскад вставить и на сторону Color, эффект тот же самый, одиночки не были удалены :)

Также попробовал убрать из класса Color коллекцию книг, чтобы со стороны цвета не было ссылок на книги. А в маппинге книги cascade="all-delete-orphan" оставил. Попробовал прогнать еще раз - эффект тот же, одиночки не были удалены.

(вот пример второго варианта)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NHPoligon" assembly="NHPoligon">

  <class name="Color" table="colors">

    <id column="Id" type="int">
      <generator class="native"/>
    </id>

    <property name="Name" type="string" column="name"/>

  </class>

</hibernate-mapping>

Код: plaintext
1.
2.
3.
public class Color
{
    public virtual string Name { get; set; }
}

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
using (NHibernate.ISession session = SessionManager.OpenSession())
{
    Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();

    book.Color = new Color(){Name = "Фиолетовый-3"};

    session.Save(book);
    session.Flush();
}

Поэтому cascade="all-delete-orphan" для меня пока что остается загадкой...
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711328
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Посмотрите, какие запросы формирует NHibernate при таком коде. (При этом предполагается, что Color - child, Book - parent.)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
using (NHibernate.ISession session = SessionManager.OpenSession())
{
    Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();

    book.Color = new Color(){Name = "Фиолетовый-3"};

    session.Save(book);
    session.Flush();
    session.Clear();

    book2Compare = session.Get<Book>(book.Id);
    book2Compare.Color = null;

    session.SaveOrUpdate(book2Compare);
    session.Flush();
}
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711393
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Шаг 1

Код: plaintext
Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();

Код: plaintext
1.
2.
3.
SELECT this_.Id as Id0_0_, this_.name as name0_0_, this_.idColor as idColor0_0_ 
FROM books this_ 
WHERE this_.name = @p0;@p0 = 'First book'


Шаг 2

Код: plaintext
1.
2.
book.Color = new Colorr() { Name = "Фиолетовый-5" };
session.Save(book);
session.Flush();

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
INSERT INTO colors (name) 
VALUES (@p0); 

select SCOPE_IDENTITY();@p0= 'Фиолетовый-5'

UPDATE books 
SET name = @p0, idColor = @p1 
WHERE Id = @p2;@p0 = 'First book', @p1 =  14 , @p2 =  33 

Шаг 3

Код: plaintext
1.
2.
session.Clear();

Book book2Compare = session.Get<Book>(book.Id);

Код: plaintext
1.
2.
SELECT book0_.Id as Id0_0_, book0_.name as name0_0_, book0_.idColor as idColor0_0_ 
FROM books book0_ 
WHERE book0_.Id=@p0;@p0 =  33 

Шаг 4

Код: plaintext
1.
2.
3.
4.
book2Compare.Color = null;

session.SaveOrUpdate(book2Compare);
session.Flush();

Код: plaintext
UPDATE books SET name = @p0, idColor = @p1 WHERE Id = @p2;@p0 = 'First book', @p1 = NULL, @p2 =  33 
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711575
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
После изучения документации и нескольких опытов установлено следующее: all-delete-orphan работает только для коллекций. Я об этому успел успешно забыть.
Проверка ниже. При "all" NHibernate только обновит Color (BookId = null), а при "all-delete-orphan" еще и удалит Color.

опыты
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
    public class Book
    {
        private IList<Color> _colors;
        private string _name;
        private int _id;

        public Book()
        {
            _colors = new List<Color>();
        }
        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public virtual IList<Color> Colors
        {
            get { return _colors; }
            set { _colors = value; }
        }

        public virtual int Id
        {
            get { return _id; }
            set { _id = value; }
        }
    }

    public class Color
    {
        private int _id;
        private string _name;

        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public virtual int Id
        {
            get { return _id; }
            set { _id = value; }
        }
    }

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NHibernate.Probing" assembly="NHibernate.Probing">

	<class name="Book" table="books">
		<id name="Id" column="Id">
			<generator class="native" />
		</id>
		<property name="Name" type="string" column="name" />
		<bag name="Colors" cascade="all">
			<key column="BookId"/>
			<one-to-many class="Color"/>
		</bag>
	</class>

	<class name="Color" table="colors">
		<id column="Id" name="Id">
			<generator class="native" />
		</id>
		<property name="Name" type="string" column="name" />
	</class>

</hibernate-mapping>

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
 [TestFixture]
    public class NHibernateFixture
    {
        #region Setup/Teardown

        [SetUp]
        public void SetUp()
        {
            _config = new Configuration();
            _config.Configure("hibernate.cfg.xml");

            _sessionFactory = _config.BuildSessionFactory();
            new SchemaExport(_config).Drop(false, true);
            new SchemaExport(_config).Execute(false, true, false);
        }

        #endregion

        private ISessionFactory _sessionFactory;
        private Configuration _config;

        [Test]
        public void Test()
        {
            using (ISession session = _sessionFactory.OpenSession())
            {
                Book book = new Book();

                book.Colors.Add(new Color());

                session.SaveOrUpdate(book);
                session.Flush();
                session.Clear();

                Book book2Compare = session.Get<Book>(book.Id);
                book2Compare.Colors.Clear();

                session.SaveOrUpdate(book2Compare);
                session.Flush();
            }
        }
    }

...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711683
Pregamil
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Супер! Спасибо большое, буду знать :)
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711836
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtor,

Дело принципа, сделал приложение по данному мапу, мап идентичный таблици тоже
вот поведение хибера.
1 вытаскивание книги
Код: plaintext
SELECT this_.Id as Id0_0_, this_.Name as Name0_0_, this_.idColor as idColor0_0_ FROM Book1 this_ WHERE  this_.Name = @p0; @p0 = 'First book'

2 удаление книг.

Код: plaintext
1.
//вытаскиваем цвет книги.
SELECT color0_.Id as Id1_0_, color0_.Name as Name1_0_ FROM Color color0_ WHERE color0_.Id=@p0; @p0 = '12'

втаскиваем все книги этого цвета
Код: plaintext
SELECT book0_.IdColor as IdColor__1_, book0_.Id as Id1_, book0_.Id as Id0_0_, book0_.Name as Name0_0_, book0_.idColor as idColor0_0_ FROM Book1 book0_ WHERE book0_.IdColor=@p0; @p0 = '12'
делаем все книги что не смогли вытащить мусором
Код: plaintext
UPDATE Book1 SET IdColor = null WHERE IdColor = @p0; @p0 = '12'

удаляем книги ( 2 книги ссылаются на один цвет)
и цвет
Код: plaintext
1.
2.
2010-06-28 17:39:46,343 [11] DEBUG NHibernate.SQL - DELETE FROM Book1 WHERE Id = @p0; @p0 = '5'
2010-06-28 17:39:46,343 [11] DEBUG NHibernate.SQL - DELETE FROM Book1 WHERE Id = @p0; @p0 = '6'
2010-06-28 17:39:46,359 [11] DEBUG NHibernate.SQL - DELETE FROM Color WHERE Id = @p0; @p0 = '12'
стоит отметить, насчет мусора, это при ленивой загрузке
при не ленивой, если книга добавлена в другой сессии жибер уже не тянет все книги одного цвета, он просто отправляет добавленные в мусор


......................хибер 1.2
Код: plaintext
1.
2.
3.
<property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>

запросы взяты из лога хибера.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711865
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи,

приложите код на C#, как и что делаете.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711871
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtor,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
private void button1_Click(object sender, EventArgs e)
        {
            ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();
            Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();
            session.Delete(book);
            session.Flush();
        }
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711878
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи,

Не видно, где и сколько книг вы создаёте, и где устанавливаете связи между ними.


Мой ответ Чемберлену
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
    public class Book
    {
        private IList<Color> _colors;
        private string _name;
        private int _id;

        public Book()
        {
            _colors = new List<Color>();
        }
        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public virtual IList<Color> Colors
        {
            get { return _colors; }
            set { _colors = value; }
        }

        public virtual int Id
        {
            get { return _id; }
            set { _id = value; }
        }
    }

    public class Color
    {
        private int _id;
        private string _name;
        private Book _book;

        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public virtual int Id
        {
            get { return _id; }
            set { _id = value; }
        }

        public virtual Book Book
        {
            get { return _book; }
            set { _book = value; }
        }

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
<?xml version="1.0" encoding="utf-8"?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NHibernate.Probing" assembly="NHibernate.Probing" default-lazy="false">

	<class name="Book" table="books">
		<id name="Id" column="Id">
			<generator class="native" />
		</id>
		<property name="Name" type="string" column="name" />
		<bag name="Colors" cascade="all-delete-orphan" inverse="true">
			<key column="BookId"/>
			<one-to-many class="Color" />
		</bag>
	</class>

	<class name="Color" table="colors">
		<id column="Id" name="Id">
			<generator class="native" />
		</id>
		<property name="Name" type="string" column="name" />
		<many-to-one name="Book" class="Book" cascade="all">
			<column name="idColor" />
		</many-to-one>
	</class>

</hibernate-mapping>

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
    [TestFixture]
    public class NHibernateFixture
    {
        #region Setup/Teardown

        [SetUp]
        public void SetUp()
        {
            _config = new Configuration();
            _config.Configure("hibernate.cfg.xml");

            _sessionFactory = _config.BuildSessionFactory();
            new SchemaExport(_config).Drop(false, true);
            new SchemaExport(_config).Execute(true, true, false);
        }

        #endregion

        private ISessionFactory _sessionFactory;
        private Configuration _config;

        [Test]
        public void Test2()
        {
            using (ISession session = _sessionFactory.OpenSession())
            {
                Book book = new Book();

                book.Colors.Add(new Color());
                book.Colors.Add(new Color());
                book.Colors[0].Book = book;
                book.Colors[1].Book = book;

                session.SaveOrUpdate(book);
                session.Flush();
                session.Clear();

                Color color = session.Get<Color>(book.Colors[1].Id);
                session.Delete(color);
                session.Flush();
            }
        }
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
 create table books (
        Id INT IDENTITY NOT NULL,
       name NVARCHAR(255) null,
       primary key (Id)
    )

    create table colors (
        Id INT IDENTITY NOT NULL,
       name NVARCHAR(255) null,
       idColor INT null,
       BookId INT null,
       primary key (Id)
    )

    alter table colors 
        add constraint FK5E59605F263D6D63 
        foreign key (idColor) 
        references books

    alter table colors 
        add constraint FK5E59605FDBD2D929 
        foreign key (BookId) 
        references books
NHibernate: INSERT INTO books (name) VALUES (@p0); select SCOPE_IDENTITY();@p0 = NULL
NHibernate: INSERT INTO colors (name, idColor) VALUES (@p0, @p1); select SCOPE_IDENTITY();@p0 = NULL, @p1 = 1
NHibernate: INSERT INTO colors (name, idColor) VALUES (@p0, @p1); select SCOPE_IDENTITY();@p0 = NULL, @p1 = 1
NHibernate: SELECT color0_.Id as Id1_1_, color0_.name as name1_1_, color0_.idColor as idColor1_1_, book1_.Id as Id0_0_, book1_.name as name0_0_ FROM colors color0_ left outer join books book1_ on color0_.idColor=book1_.Id WHERE color0_.Id=@p0;@p0 = 2
NHibernate: SELECT colors0_.BookId as BookId2_, colors0_.Id as Id2_, colors0_.Id as Id1_1_, colors0_.name as name1_1_, colors0_.idColor as idColor1_1_, book1_.Id as Id0_0_, book1_.name as name0_0_ FROM colors colors0_ left outer join books book1_ on colors0_.idColor=book1_.Id WHERE colors0_.BookId=@p0;@p0 = 1
NHibernate: DELETE FROM colors WHERE Id = @p0;@p0 = 2
NHibernate: DELETE FROM books WHERE Id = @p0;@p0 = 1
18:20:38,455 ERROR [   7] AbstractBatcher [(null)]- Could not execute command: DELETE FROM books WHERE Id = @p0
System.Data.SqlClient.SqlException: DELETE statement conflicted with COLUMN REFERENCE constraint 'FK5E59605F263D6D63'. The conflict occurred in database 'Integration_Tests', table 'colors', column 'idColor'.
The statement has been terminated.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711951
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtor,

Прошу прощения, при мапе inverse потавил по дефолту
вот он херачит упдате.
что стоит заметить тут true не уместно при неленивой загрузке.
можем получить конфликт при удалении, если после вытаскивания, ктонить добавит еще одну буки
с таким же цветом.
ибо он не полезет в базу а просто будет удалять что вытащил джойном при первом селекте
и споткнется на солоре, а если транзакцию забыть до и книги потеряем.
а так, удаляет корректно.......
зы применительно к этому коду.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36711965
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtor,

а разве в буке мешок, в колоре мешок должен быть,
хотя какая разница где..
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36712064
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я бы в тестах применил рефреш для приближения к боевым условиям.
ленивая, inverse девфолтный.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
 
            Book _book = new Book();
            _book.Color = new Color { Name = "asass" };
            _book.Name = "First book";
            session.Save(_book);
            Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();
          
            session.Refresh(book.Color);

            session.Delete(book);
            session.Flush();
           


лог
[SRC c#]2010-06-28 21:02:11,343 [11] DEBUG NHibernate.SQL - INSERT INTO Color (Name) VALUES (@p0); select SCOPE_IDENTITY(); @p0 = 'asass'
2010-06-28 21:02:11,734 [11] DEBUG NHibernate.SQL - INSERT INTO Book1 (Name, idColor) VALUES (@p0, @p1); select SCOPE_IDENTITY(); @p0 = 'First book', @p1 = '61'
2010-06-28 21:02:11,828 [11] DEBUG NHibernate.SQL - SELECT this_.Id as Id0_0_, this_.Name as Name0_0_, this_.idColor as idColor0_0_ FROM Book1 this_ WHERE this_.IdColor!='0' AND this_.Name = @p0; @p0 = 'First book'
2010-06-28 21:02:11,859 [11] DEBUG NHibernate.SQL - SELECT color0_.Id as Id1_0_, color0_.Name as Name1_0_ FROM Color color0_ WHERE color0_.Id=@p0; @p0 = '61'
2010-06-28 21:02:11,890 [11] DEBUG NHibernate.SQL - SELECT book0_.IdColor as IdColor__1_, book0_.Id as Id1_, book0_.Id as Id0_0_, book0_.Name as Name0_0_, book0_.idColor as idColor0_0_ FROM Book1 book0_ WHERE book0_.IdColor=@p0; @p0 = '61'
2010-06-28 21:02:11,937 [11] DEBUG NHibernate.SQL - UPDATE Book1 SET IdColor = null WHERE IdColor = @p0; @p0 = '61'
2010-06-28 21:02:11,953 [11] DEBUG NHibernate.SQL - DELETE FROM Book1 WHERE Id = @p0; @p0 = '7'
2010-06-28 21:02:11,953 [11] DEBUG NHibernate.SQL - DELETE FROM Color WHERE Id = @p0; @p0 = '61'
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36712477
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи,

меж тем почти вся правда ваша. Вчера под вечер ошибся в маппинге Color. Аналогичная ошибка была и у топикстартера. Копипаст - зло. Правильный выглдяит так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
	<class name="Color" table="colors">
		<id column="Id" name="Id">
			<generator class="native" />
		</id>
		<property name="Name" type="string" column="name" />
		<many-to-one name="Book" class="Book" cascade="all">
			<column name="BookId" /> //Тут было idColor
		</many-to-one>
	</class>
С таким раскладом всё удаляется корректно. Но я бы всё равно не рекомендовал делать двунаправленное управление ассоциациями. Будет проще жить, если временем жизни будет управлять только один коренной объект.

Но кое-что требует отдельного уточнения.

Где-то в степиSolYUtor,

Прошу прощения, при мапе inverse потавил по дефолту
вот он херачит упдате.
что стоит заметить тут true не уместно при неленивой загрузке.
При чем тут вообще ленивая загрузка? Inverse влияет лишь на то, с какой стороны будет контролироваться изменения в двунаправленной ассоциации. Поэтому inverse=false всегда уместно, если у вас двунаправленная ассоциация, дабы NHibernate не делал лишней работы!
Где-то в степи
можем получить конфликт при удалении, если после вытаскивания, ктонить добавит еще одну буки
с таким же цветом.
ибо он не полезет в базу а просто будет удалять что вытащил джойном при первом селекте
и споткнется на солоре, а если транзакцию забыть до и книги потеряем.
а так, удаляет корректно.......
зы применительно к этому коду.

Конфликты всегда были есть и будут есть. Для этого были придуманы транзакции, но напрямую к NHibernate эта тема не относится.
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36713622
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtor,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
Поробую обьяснить.
все согласно мапу топикмейкера. инверсия в мешке true, не ленивая загрузка.


 ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();
пользователь открывает сессию поработать с книгой

  Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();

2010-06-29 16:48:14,796 [10] DEBUG NHibernate.SQL - SELECT this_.Id as Id0_1_, this_.Name as Name0_1_, this_.idColor as idColor0_1_, color2_.Id as Id1_0_, color2_.Name as Name1_0_ FROM Book2 this_ left outer join Color color2_ on this_.idColor=color2_.Id WHERE this_.IdColor!='0' AND this_.Name = @p0; @p0 = 'First book'
2010-06-29 16:48:15,250 [10] DEBUG NHibernate.SQL - SELECT book0_.IdColor as IdColor__2_, book0_.Id as Id2_, book0_.Id as Id0_1_, book0_.Name as Name0_1_, book0_.idColor as idColor0_1_, color1_.Id as Id1_0_, color1_.Name as Name1_0_ FROM Book2 book0_ left outer join Color color1_ on book0_.idColor=color1_.Id WHERE book0_.IdColor=@p0; @p0 = '28'

работает с книгой у меня две книги с одним цветом ( он их вытащил)
в это время другой пользователь добавил третью книгу.

первый пользователь решил удалить выбранную книгу  согласно мапу.
 ITransaction _tr = session.BeginTransaction();
            session.Delete(book);
          
            session.Flush();

2010-06-29 16:51:53,281 [10] DEBUG NHibernate.SQL - DELETE FROM Book2 WHERE Id = @p0; @p0 = '1'
2010-06-29 16:51:53,296 [10] DEBUG NHibernate.SQL - DELETE FROM Book2 WHERE Id = @p0; @p0 = '2'
// в этом месте на удалении солора екцепшен, так как естьт третья книга, и  хибер о ней ничего не знает
2010-06-29 16:51:53,312 [10] DEBUG NHibernate.SQL - DELETE FROM Color WHERE Id = @p0; @p0 = '28'

теперь инверсию в мешке сделаем дефлотную, 

 посмотрим что получится.

 Book book = (Book)session.CreateCriteria(typeof(Book)).Add(Expression.Eq("Name", "First book")).UniqueResult();

2010-06-29 17:09:08,734 [11] DEBUG NHibernate.SQL - SELECT this_.Id as Id0_1_, this_.Name as Name0_1_, this_.idColor as idColor0_1_, color2_.Id as Id1_0_, color2_.Name as Name1_0_ FROM Book2 this_ left outer join Color color2_ on this_.idColor=color2_.Id WHERE this_.IdColor!='0' AND this_.Name = @p0; @p0 = 'First book'
2010-06-29 17:09:09,171 [11] DEBUG NHibernate.SQL - SELECT book0_.IdColor as IdColor__2_, book0_.Id as Id2_, book0_.Id as Id0_1_, book0_.Name as Name0_1_, book0_.idColor as idColor0_1_, color1_.Id as Id1_0_, color1_.Name as Name1_0_ FROM Book2 book0_ left outer join Color color1_ on book0_.idColor=color1_.Id WHERE book0_.IdColor=@p0; @p0 = '28'

ITransaction _tr = session.BeginTransaction();
            session.Delete(book);
            _tr.Commit();
            session.Flush();




2010-06-29 17:11:16,484 [10] DEBUG NHibernate.SQL - UPDATE Book2 SET IdColor = null WHERE IdColor = @p0; @p0 = '28'
2010-06-29 17:11:16,515 [10] DEBUG NHibernate.SQL - DELETE FROM Book2 WHERE Id = @p0; @p0 = '1'
2010-06-29 17:11:16,515 [10] DEBUG NHibernate.SQL - DELETE FROM Book2 WHERE Id = @p0; @p0 = '2'
2010-06-29 17:11:16,531 [10] DEBUG NHibernate.SQL - DELETE FROM Color WHERE Id = @p0; @p0 = '28'
он упдатой книгу добаденную другим пользователем отправляет в мусор, исключения нет
ну естестнно where в классе на IdColor не забываем
...
Рейтинг: 0 / 0
NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
    #36713981
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи,

Я так и не понял, где проблема. Чётко ее сформулируйте.
...
Рейтинг: 0 / 0
32 сообщений из 32, показаны все 2 страниц
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / NHibernate cascade delete - "DELETE statement conflicted with the REFERENCE constraint"
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]