2015-05-05 3 views
5

У меня есть два стола, tableA и tableB.не удалось удалить коллекцию: [NHibernate.Exceptions.GenericADOException]

TABLEA есть колонка: tabAId, Col2, col3 (tabAId PrimaryKey и столбец Подлинность.)

TableB есть колонки: tabAId, имя (tabAId не равно нулю)

У меня есть создать мешок в файле hbm таблицыA, для поддержания отношения судна.

<bag name="tableB" lazy="true" inverse="false" 
        batch-size="25" cascade="all-delete-orphan"> 
    <key column="tabAId" /> 
    <one-to-many class="tableB" /> 
</bag> 

Когда я пытаюсь обновить запись в TABLEA это бросить исключение, где, как у меня есть список ребенка в случае TABLEA.

[NHibernate.Exceptions.GenericADOException] = { "не удалось удалить коллекцию: [MIHR.Entities.tableA.tableB # 21] [SQL: UPDATE SET dbo.tableB tabAId = NULL WHERE tabAId = @ p0]" }

InnerException = { "не удается вставить значение NULL в столбце 'tabAId', таблица 'SA_MIHR_DEV.dbo.tableB';... колонка не позволяет аннулирует UPDATE не может \ г утверждение \ NThe было прекращено" }

ответ

8

Существует только два способа решения этой проблемы.

1) не используют inverse="false"

<bag name="tableB" lazy="true" inverse="true" // instead of false 
        batch-size="25" cascade="all-delete-orphan"> 
    <key column="tabAId" /> 
    <one-to-many class="tableB" /> 
</bag> 

Этот параметр (обратное = "истина") будет инструктировать NHibernate непосредственно удалить элемент из БД.

При использовании inverse="false" будет вообще всегда приводит к:

  • UPDATE (с нулевым) == акт удаления из коллекции
  • УДАЛИТЬ элемент == акт каскада

2) сделать ссылочную колонку нулевой

Это означает, что мы можем оставить NHibernate для ОБНОВЛЕНИЯ и УДАЛЕНИЯ. Поскольку столбец теперь имеет значение NULL.

Это только два способа решить эту проблему.

Мое предпочтение было бы: обратное = «истинный»

Для правильной работы с inverse="true" мы всегда должны назначить обе стороны отношения в C#.Это необходимо для Add(), операции ВСТАВИТЬ:

Parent parent = new Parent(); 
Child child = new Child 
{ 
    ... 
    Parent = parent, 
}; 
// unless initialized in the Parent type, we can do it here 
parent.Children = parent.Children ?? new List<Child>(); 
parent.Children.Add(child); 

// now just parent could be saved 
// and NHibernate will do all the cascade as expected 
// and because of inverse mapping - the most effective way 
session.Save(parent); 

Как мы можем видеть, мы назначили - явно - обе стороны отношений. Это необходимо для получения прибыли от обратного отображения NHibernate. И это также хорошая практика, потому что позже, когда мы загружаем данные из DB, мы ожидаем, что NHibernate позаботится о том, чтобы установить для нас

+1

Если я установил Inverse = "true", то он не будет вставлять вновь созданное значение столбца Identity в дочернюю таблицу, вставляя новую запись в родительскую таблицу. –

+0

Kohler: Расскажите, пожалуйста, как это сделать, когда я установлю 'inversr =" true "'. –

+0

Теперь вы должны это увидеть ... Я обновил свой ответ. Конечно, ваш дочерний объект должен иметь ссылку на родителя. Проверьте это http://stackoverflow.com/a/30005490/1679310 для ВСЕХ ДЕТАЛЕЙ –