2015-01-23 5 views
2

Как гласит название, в основном я хочу изменить родителя ребенка. Но когда я пытаюсь сделать это, я получаю исключение «ObjectDeletedException: удаленный объект будет повторно сохранен cascade (удалить удаленный объект из ассоциаций)».NHibernate: Change Parent - «удаленный объект будет повторно сохранен каскадом»

Я уже много часов работаю в Интернете, но ни одно из решений, которые я нашел, не работало для меня !!

Это мои классы участвуют:

public class Parent: Entity 
{ 
    public virtual IList<Child> Children { get; set; } 
} 

public class Child: Entity 
{ 
    public virtual DateTime? CancellationDate { get; set; } 
} 

Класс Entity является тот, который имеет свойство Id.

Это родителя отображение (Parents.hbm.xml):

<bag name="Children" cascade="all-delete-orphan" table="Schema.Child" where="CancellationDate is null"> 
    <key column="ParentID"/> 
    <one-to-many class="Namespace.Child"/> 
</bag> 

И это кусок кода, где я пытаюсь reasign ребенка другому родителю:

foreach(Child c in Parent1.Children) 
{ 
    Parent2.Children.Add(c); 
} 

Но то session.Flush() выдает исключение выше. Я предполагаю, что проблема в том, что с тех пор, как ребенок изменил родителя, из-за каскадного NHibernate пришлось бы избавиться от Ребенка, но затем он был переназначен родителям anothet, поэтому, опять же из-за каскада, за исключением ребенка.

Я уже попытался изменить отображение и удаление ребенка из коллекции бывшего родителя (до или после того, как я задаю его к другому родителю), но ни один из тех, кто работал ...

Любая помощь будет очень признателен !!

Спасибо!

+0

как возможное решение, попробуйте добавить КОПИИ родителей1 ребенка к parent2. имейте в виду, что это создаст (после сохранения) новые записи в db, связанные с parent2, и удалит строки родительских 1 дочерних элементов. Или вы просто хотите обновить ParentId? – ASh

+0

Да, я думал об этом решении, но я не могу создать новый, Id ребенка должен остаться тем же ... Спасибо в любом случае !! –

+0

полезно? http://stackoverflow.com/questions/2763985/how-do-i-change-a-childs-parent-in-nhibernate-when-cascade-is-delete-all-orphan – ASh

ответ

0

Я видел ваше заявление об отказе: ... Я уже много часов работаю в Интернете, но ни одно из решений, которые я нашел, не работал для меня !!

Но в целом, в приведенном выше примере просто никогда не состоянии (ре) производить ObjectDeletedException.

Существует даже встроенный тест в NHibernate, что проверить, что:

NHibernate.Test.NHSpecificTest.NH1531 SampleTest ReparentingShouldNotFail

[Test] 
public void ReparentingShouldNotFail() 
{ 
    FillDb(); 
    using (ISession session = OpenSession()) 
    { 
     var parent1 = session.Get<Parent>(1); 
     var parent2 = session.Get<Parent>(2); 

     Assert.AreEqual(1, parent1.Children.Count); 
     Assert.AreEqual(0, parent2.Children.Count); 

     Child p1Child = parent1.Children[0]; 

     Assert.IsNotNull(p1Child); 

     parent1.DetachAllChildren(); 
     parent2.AttachNewChild(p1Child); 

     session.Update(parent1); 
     session.Update(parent2); 

     // NHibernate.ObjectDeletedException : 
     // deleted object would be re-saved by cascade 
     // (remove deleted object from associations) 
     // [NHibernate.Test.NHSpecificTest.NH1531.Child#0] 

     session.Flush(); 
    } 
    ... 

Этот тест проходит.

Итак, где проблема? просто где-то в коде, который вы не показывали. Подробное описание такого вопроса можно найти здесь:

, а также некоторые обсуждения и больше намеков здесь

ObjectDeletedException(» удаленный объект будет повторно сохранен ...") почти всегда означает: некоторый объект был УДАЛЕН. Это информация хранится в текущем session. Но есть еще некоторая коллекция, ссылающаяся на нее ...

0

как-то я не могу получить доступ к учетной записи, с которой я задал вопрос.

Оказывается, что мы не стирать Специальные условия для данных, только логически, поэтому изменение каскад «сохранить обновиться» решена проблема

Эта ссылка объясняет очень четко вопрос о reparenting в NHibernate:.

http://osdir.com/ml/nhusers/2009-09/msg00323.html

0

Я знаю, что его было какое-то время, и я не знаю, если вам все еще нужно, но я недавно столкнулся с этим вопросом, и вот фрагмент кода, который работал для меня:

parent.Children.Remove(child); 
session.Delete(child); 
session.Evict(child); 
child.ID = 0; 
child.Parent = otherParent; 
otherParent.Children.Add(child); 

В основном, это удаляет старый ребенок и добавляет совершенно новый с новым идентификатором и теми же свойствами для другого родителя. Это не позволяет вам сделать глубокую копию дочернего объекта, чтобы добавить его в новый родитель. То, что он делает, - это отключение ребенка от его старого родителя, удаление его (из сеанса), выселение его (принуждение nhibernate забыть о существовании объекта), сброс идентификатора (при условии, что вы используете столбец идентификатора sql-семени), переименование его затем добавив его в коллекцию нового родителя.

Используя эту тактику, я все еще могу сохранить «каскад-все-удалить-сирота» на родительском сопоставлении, в то время как не нужно делать отношения «обратными». Надеюсь, что это поможет любому, кто проходит эту проблему, может быть настоящей болью ...