NHibernate: вызов .RemoveAll в коллекции - PullRequest
3 голосов
/ 27 января 2012

У меня проблема с невозможностью использования .RemoveAll при получении коллекции через NHibernate.

У меня есть объект с именем Order, который сохраняется через NHibernate.

Order имеет много OrderItems.Вот мое отображение этих отношений:

mapping.HasMany(o => o.Items)
                   .Cascade.AllDeleteOrphan()
                   .AsList()
                   .Inverse();

В моем домене это выглядит так:

public virtual IList<OrderItem> Items { get; set; }

Насколько я понимаю, я должен использовать IList, потому что NHibernate имеет егособственная реализация List.

Теперь я хочу удалить элемент из моего Order, используя этот метод в моем Order классе:

public virtual void RemoveItem(string variantSku)
{
    items.RemoveAll(x => x.Variant.VariantSku == variantSku);
}

Это не работает, потому чтоIList не имеет этого метода.

Я пытался:

items.ToList().RemoveAll(x => x.Variant.VariantSku == variantSku);

Но, похоже, это не работает.Я понимаю, что items.ToList() фактически создает копию исходного списка, поэтому я думаю, что я мог бы попробовать:

var itemsList = items.ToList();
itemsList.RemoveAll(...)

Но тогда это все еще сохраняется через NHibernate?

Мой вопрос: можетЯ на самом деле использую .RemoveAll в этом контексте, или я должен подумать о другом способе удаления элемента?

Ответы [ 2 ]

4 голосов
/ 27 января 2012

Коллекция отображается как обратная сторона отношения, поэтому помимо удаления элемента из коллекции необходимо аннулировать ссылку на Заказ на стороне OrderItem.Поэтому метод RemoveAll или метод extension не будут выполнять эту работу.

Я бы справился с этим следующим образом:

public virtual void RemoveItem(string variantSku)
{
    var itemsToRemove = items.Where(x => x.Variant.VariantSku == variantSku).ToArray();
    foreach(var item in itemsToRemove)
    {
       item.Order = null;
       items.Remove(item);
    }
}

Я также предлагаю использовать set вместо отображения пакетов.

3 голосов
/ 27 января 2012

Вы всегда можете создать свой собственный RemoveAll метод расширения:

public static void RemoveAll<T>(this IList<T> source, Predicate<T> predicate)
{
    // TODO: Argument non-nullity validation

    // Optimization
    List<T> list = source as List<T>
    if (list != null)
    {
        list.RemoveAll(predicate);
        return;
    }

    // Slow way
    for (int i = source.Count - 1; i >= 0; i--)
    {
        if (predicate(source[i]))
        {
            source.RemoveAt(i);
        }
    }
}

Я бы ожидал, что NHibernate позаботится о самой коллекции - просто удаление элемента из List<T> - это не то, что NHibernate может "заметить".

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...