2009-11-12 4 views
2

Используя NHibernate, я ищу способ автоматического обновления сохраненных коллекций при удалении сохраненного элемента. Например:NHibernate: удалять элемент из сохраненной коллекции автоматически

var post = GetNewPost(); 
var blog = GetCurrentBlog(); 
blog.Posts.Add(post); 
BlogRepository.Update(blog); 

User.Posts.Add(post); 
UserRepository.Update(user); 

---- 

// Somewhere else 
var blog = GetCurrentBlog(); 
var post = blog.Posts.Last(); 
blog.Posts.Remove(post); 

NHibSession.Flush(); // Throws an ObjectDeletedException due to 'post' 
        // still being in the User.Posts collection 

Я понимаю, что могут быть проблемы с моделью и/или отображения в этом примере, но эти вопросы в сторону, я хочу, чтобы найти способ, чтобы получить коллекцию User.Posts автоматически обновляться , т.е. удалить «сообщение» от себя. (Может быть, это не самый лучший пример в мире, но предположим, что существует много блогов и многих Пользователей, не связанных друг с другом, кроме как через Posts. Понимают, что это фасад.)

В этом примере я использую только один Сессия NHibernate. Я готов настроить это, но я ищу схему, и она должна быть прозрачной для модели. События NHibernate также находятся на столе, если можно показать, что это хорошая практика.

Я считаю, что LINQ to SQL может справиться с этой ситуацией, поэтому я немного удивлен, что NHibernate не может (в лучшем случае из моих поисковых способностей). Существуют ли какие-либо дополнительные рамки, которые могут?

Вот соответствующие отображения для этого примера:

<class name="App.Core.Domain.Post, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Posts" xmlns="urn:nhibernate-mapping-2.2"> 
    <id name="Id" type="Guid" column="PostId"> 
     <generator class="assigned" /> 
    </id> 
    ... 
    <many-to-one cascade="save-update" access="field.pascalcase-underscore" name="Blog" column="BlogId" /> 

    <many-to-one cascade="save-update" access="field.pascalcase-underscore" name="User" column="UserId" /> 
</class> 

<class name="App.Core.Domain.Blog, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Blogs" xmlns="urn:nhibernate-mapping-2.2"> 
    <id name="Id" type="Guid" column="BlogId"> 
     <generator class="assigned" /> 
    </id> 
    ... 
    <bag name="Posts" cascade="all" inverse="true" access="field.pascalcase-underscore"> 
     <key column="PostId" /> 
     <one-to-many class="App.Core.Domain.Post, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
</class> 

<class name="App.Core.Domain.User, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Users" xmlns="urn:nhibernate-mapping-2.2"> 
    <id name="Id" type="Guid" column="UserId"> 
     <generator class="assigned" /> 
    </id> 
    ... 
    <bag name="Posts" cascade="all" inverse="true" access="field.pascalcase-underscore"> 
     <key column="PostId" /> 
     <one-to-many class="App.Core.Domain.Post, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
</class> 
+0

Не могли бы вы вставить свои файлы сопоставления для Blog и Post в ответ? – reach4thelasers

ответ

0

Попробуйте удалить каскад = все на сумке сообщений. Когда вы очищаете сеанс, сборка Post каскадирует сообщение и пытается его обновить.

Вы создаете новый пост, используя Blog.Posts.Add, но пытающийся удалить его с помощью PostsRepository.Delete (post). Выберите одну стратегию и придерживайтесь ее.

+0

Мне нравится ваше предложение, но Уэс неплохо объяснил, почему это не совсем решение. Он добавляет коллекцию User.FavoritePosts, которая также сохраняется, а также содержит ссылку на сообщение, которое нужно удалить.Используя только один сеанс, я должен быть дотошным в отношении того, какие коллекции ссылаются на это сообщение, и проверить и удалить его из * всех * из них, прежде чем я попытаюсь очистить сеанс, или я получу то же ObjectDeletedException. – Tyson

0

Я хочу, чтобы уточнить этот вопрос еще, скажем, мы расширим ситуацию следующего новое Model

Что происходит, когда наш пост связан с другим лицом, кроме блог? Даже если мы позаботимся о том, чтобы удалить сообщение только через Blog.Posts.Remove, какова общая стратегия обработки очистки других ассоциаций? Предположим, мы не можем заполнить все элементы одним агрегированным корнем, если бы смогли, мы могли бы очистить их все через AR. Итак, в основном у нас есть ассоциации между совокупными корнями, какова наилучшая практика их очистки? В этом примере пользователь может перечислить свои любимые сообщения, но это всего лишь однопользовательская ассоциация от пользователя для публикации, связи нет.

Нужна ли нам служба домена, чтобы удалить/удалить объект из домена (а не просто сделать его временным, но получить его GCed), который удалит все ассоциации? Это сделает NHibernate счастливым, когда оно сохранится. В этом случае нам нужно будет удалить сообщение не только из блога, но и из любого пользователя, который помечен как избранный. Должно ли это жить в службе домена, службе приложения? Как мы используем эту услугу, если происходит каскадное удаление, скажем, мы удаляем блог с сообщениями, отмеченными фаворитами, если мы будем использовать события NHib и обнаруживать, что сообщения были удалены и объединены в ассоциации очистки?

Я знаю, что некоторые люди предлагают использовать каскадирование FK в базе данных, но это будет работать только в том случае, если ассоциации не загружаются в сеанс. Если они загружены, их нужно удалить. То, что мне не нравится в этом подходе, заключается в том, что оно нарушает идею наличия реальной модели в памяти, которая действует так же, как если бы NHib и база данных не были там. Мысли?

+0

Какую программу вы используете для создания этих диаграмм? – reach4thelasers

+0

http://yuml.me/ – Tyson

Смежные вопросы