2012-01-09 14 views
5

(EF)EntityCollectionにアイテムを追加する拡張メソッドを書いた。 IEnumerable( "items")のコレクションがforeach内の最初のループの後に変更されたと言って面白いエラーが発生しました。アイテムをitems.ToList()に変換すると(下のコードのように)、うまく動作します。C#IEnumerableミステリーの修正、私のIEnumerableの変更は何ですか?

ToList()は、foreachが動作するアイテムのコピーを生成することを完全に理解しています。

私が理解できないのは、IEnumerableをforeachしているときにIEnumerableを変更していることです。

更新:どういうわけか、items変数がcollections変数と同じであるようですか?

アップデート2:私は、コレクションと実体がEFのエンティティの追跡によって影響を受ける可能性があると思いますが、私はまだ理解できない理由

使用法:

ssp.ServiceAreas.ReplaceCollection(model.ServiceAreas);

はここに私の拡張メソッドです:

public static void AddOrUpdate<TEntity>(this EntityCollection<TEntity> collection, IEnumerable<TEntity> items) 
     where TEntity : EntityObject, IProjectIdentity<int>, new() 
    { 
     foreach (var item in items.ToList()) 
      collection.AddOrUpdate(item); 
    } 

    public static void AddOrUpdate<TEntity>(this EntityCollection<TEntity> collection, TEntity item) 
     where TEntity : EntityObject, IProjectIdentity<int>, new() 
    { 
     if (item.ID > 0 && collection.Any(c => c.ID == item.ID)) 
      collection.Remove(collection.First(c => c.ID == item.ID)); 
     // For now, the Remove NEVER gets hit 

     collection.Add(item); 
    } 
+3

これを変更すると「削除」されますので、追加します。 – vcsjones

+2

@vcsjonesこれは本当ですが、この状況ではそれほど単純ではありません。 –

+1

'items == collection'はあなたのケースですか? –

答えて

4
collection.Remove(collection.First(c => c.ID == item.ID)); 

あなたが反復処理しているコレクションで削除しています。

+2

しかし、繰り返しは別のコレクション(アイテム)を介してです – Erix

+0

確かに私はこれをupvotedしかし、それを試して、これは問題を引き起こすことはありません。 –

+0

確かにErix、Adam、私は明確にするために投稿を更新しました。 – sebastiaan

0

おそらくEntityCollection誰かがそれを引き継ぐのは好きではないのですか?したがって、collectionに追加すると、アイテムはitemsから削除されます。

それとも

1

items == collectionは、私は次のサンプルコードを作成したことが考えられます:あなたが期待するように、この作品

internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      var one = new List<string> {"Adam", "John"}; 

      var two = new List<string> {"Adam", "Houldsworth"}; 

      one.AddOrUpdate(two); 

      Console.Read(); 
     } 
    } 

    static class Extensions 
    { 
     public static void AddOrUpdate(this IList<string> collection, IEnumerable<string> items) 
     { 
      foreach (var item in items.ToList()) 
       collection.AddOrUpdate2(item); 
     } 

     public static void AddOrUpdate2(this IList<string> collection, string item) 
     { 
      if (collection.Any(c => c == item)) 
       collection.Remove(collection.First(c => c == item)); 

      collection.Add(item); 
     } 
    } 

、エラーがありません。したがって本質的に、問題の原因となっている行はありません。あなたが自分自身にリストを呼び出す場合の問題が発生します何

は次のとおりです。

one.AddOrUpdate(one); 

をだから私は見ることができるものから、あなたは、両方の引数と同じコレクションで、この拡張メソッドを呼び出しておく必要があります。

ご存知の場合はRemoveまたはAddの両方がコレクションを変更し、この例外を発生させます。

+0

ありがとうございますが、これは.ToList()の有無にかかわらず動作します。単にコレクションと項目が実際に異なるオブジェクトであるためです。私のコレクションオブジェクトはEFの追跡メカニズムの影響を受けている可能性があり、投稿を再度更新します。 :-) – sebastiaan

+0

@sebastiaanええ、ToListもなくてもうまくいきましたが、問題がどこに来ているかを示すために、あなたの提供するコードと似ていました。 –

0

最初の項目は常に新しい項目であるため、デフォルトではIDは初期値に設定されている可能性があります。それがコレクションに追加され、EntityFrameworkが新しいIDを生成し、最初に追加されたアイテムに割り当てます。

EntityCollectionはIDを使用して内部的にソートやその他の処理を行うため、EntityCollectionが変更したと考えている可能性があります。したがってforeach操作(おそらく同じリストを使用している)は例外をスローします。それがAdam Houldsworthによって証明されたテストケースが問題を提起しない理由です。

0
EntityCollection<Customer> customers = new EntityCollection<Customer>(); 
Customer newCustomer = new Customer() {ID = 0}; 
customers.Add(newCustomer); 
customers.AddOrUpdate(customers); 
関連する問題