2012-01-27 27 views
2

NHibernate経由でコレクションを取得するときに.RemoveAllを使用できないという問題があります。NHibernate:コレクションの.RemoveAllを呼び出す

NHibernate経由で保持するOrderというエンティティがあります。

Orderは、多くがOrderItemsです。ここでは、この関係のための私のマッピングは次のとおりです。

次のようになり、私のドメインで
mapping.HasMany(o => o.Items) 
        .Cascade.AllDeleteOrphan() 
        .AsList() 
        .Inverse(); 

:私はそれを理解したよう

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

、私はNHibernateのは、リストのそれ自身の実装を持っているのでIListを使用する必要があります。

は今、私は私の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を使用することはできますか、アイテムを削除する別の方法について検討する必要がありますか?

答えて

4

コレクションはリレーションシップの逆側としてマップされているため、コレクションからアイテムを削除するだけでなく、OrderItem側のOrderへの参照を無効にする必要があります。したがって、RemoveAllメソッドまたは拡張メソッドは、ジョブを実行しません。

私はこのようにそれを処理します:私はまた、設定の代わりに、袋のマッピングを使用することをお勧めし

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); 
    } 
} 

+0

マッピングに.Cascade.AllDeleteOrphan()がある場合は、item.Order = nullが必要かどうかわかりません。 AllDeleteOrphan()はそうではありませんか?残りは、しかし、スポットです。アイテムをforeach'ingして削除しようとしている児童の間違いをしていた。 – autonomatt

+0

item.Order = nullは孤児にするものです。そうでない場合、セッションがフラッシュされたときに再保存されます。 –

+0

実際にあなたのコードは動作しません。それでも、「コレクションは変更されました。列挙操作が実行されない可能性があります。 "私はforループを使用して終了しました。 – autonomatt

3

あなたは常にあなた自身の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が気にしたくないのであれば、変更がの場合はをローカルにすることを意味します。

+0

Ahaなので、タグ "C#"は素晴らしいJon Skeet、つまりスタックのマスターとも言えます。知っておきたいことは... :)私はこの操作について気をつけるためにNHibernateが必要です。 – autonomatt

+0

@autonomatt:返されたコレクションが 'RemoveAt'を使ってアイテムを削除してくれれば、これはうまくいくはずです。 –

関連する問題