Добавить / удалить элемент в коллекцию сумок - PullRequest
2 голосов
/ 08 сентября 2010

Я работаю с nHibernate и пытаюсь разобраться в коллекциях сумок. Моя структура данных относительно проста ...

запись:

<class name="Entry">
<id name="id" column="EntryId">
    <generator type="guid.comb"/>
</id>
    <property name="Name" column="Name"/>
<bag name="Results" table="Results" cascade="all">
    <key column="EntryId" />
    <one-to-many class="Result"/>
</bag>
</class>

Результат:

<class name="Result">
<id name="id" column="ResultId">
    <generator type="guid.comb"/>
</id>
<property name="Score" column="Score" />
<many-to-one name="Entry" class="Entry" cascade="all" />
</class>

То, что я хотел бы сделать, что, похоже, не работает, это следующее:

Entry entry = new Entry();
entry.Name = "Name";
// have tried saving at this point to:
// dbSession.SaveOrUpdate(entry);
Result result = new Result();
result.Score = 100;

entry.Results.Add(result);
dbSession.SaveOrUpdate(entry);

Кажется, создается запись в базе данных, но не запись результата. В моей базе данных у меня EntryId в качестве внешнего ключа в таблице результатов. Точно так же я хотел бы иметь возможность удалить объект результата из коллекции и сохранить его в базе данных. Я думал, что каскадная функция позаботилась об этом, но не уверен, что я сделал неправильно ...

EDIT

Теперь он добавляет объект результата в базу данных, но удаление, похоже, не работает:

Entry entry = Entry.Load(id);
entry.Results.Remove(result);
dbSession.SaveOrUpdate(entry);

Я попытался добавить cascade = "all-delete-orphan", но это, похоже, удаляет как родителей, так и детей. Я просто хочу удалить объект с одной записью из базы данных ??

Ответы [ 4 ]

2 голосов
/ 15 сентября 2010

В конце концов, это привело к тому, что мои отображения файлов hbm были неверными.

Entry.hbm.xml

<bag name="Results" table="Result" lazy="false" inverse="true" cascade="all-delete-orphan">
    <key column="EntryId"/>
    <one-to-many class="Result"/>
</bag>

Result.hbm.xml

<many-to-one name="Entry" class="Entry" column="EntryId"/>

У меня изначально был cascade = "all-delete-orphan" на многихсопоставление «один к одному», что было неверным.Случилось так, что все дочерние и родительские записи были удалены.

Теперь я могу добавлять и удалять с помощью следующего:

Result r = new Result();
Entry entry = new Entry();
// AddResult method sets the Entry object of the Result
// result.Entry = this;
entry.AddResult(r);
session.SaveOrUpdate(entry);

Удалить:

entry.Results.Remove(result);
session.SaveOrUpdate(entry);
0 голосов
/ 03 января 2015

если вы используете Mapping by Code, тогда используйте опции Cascade.All и Cascade.DeleteOrphans. в отличие от сопоставления xml, в «Сопоставлении по коду» нет единой опции «all-delete-orphan».

 Bag(x => x.Results, c =>
        {
            c.Key(k =>
            {
                k.Column("EntryId");
            });               
            c.Cascade(Cascade.All | Cascade.DeleteOrphans);
        }, r => r.OneToMany())
0 голосов
/ 12 сентября 2010

Я заметил, что в вашей коллекции вы определили столбец FK как:

<key column="EntryId" />

Но вы не переопределяете column в many-to-one, что означает, что у вас есть два разных столбца (Entry и EntryId) для одинаковых отношений.

Это может быть или нет ... но проверять не мешает: -)

0 голосов
/ 11 сентября 2010

Чтобы добавить в коллекцию, вам нужно явно сохранить дочерний объект при его добавлении.То же самое при удалении объекта из коллекции.

Таким образом, вы должны сделать:

entry.Results.Add(result);
session.Save(result);
session.Save(entry);
session.Flush();

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

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

entry.Results.Remove(result);
session.Delete(result);
session.Update(entry);
session.Flush();

Вы удалили результат из коллекции и обновили запись.Это только говорит Nhibernate об удалении связи между записью и результатом - вы фактически никогда не удаляли сам объект результата.

...