簡體   English   中英

EF 4.1和“集合被修改; 枚舉操作可能無法執行。“異常

[英]EF 4.1 and “Collection was modified; enumeration operation may not execute.” exception

在過去的兩天里,這讓我瘋狂。 我有3個非常基本的類(好了,為了便於閱讀而減少)

public class Employee 
{
    public string Name { set; get; }
    virtual public Employer Employer { set; get; }

    public Employee(string name)
    {
        this.Name = name;
    }
}

// this basically ties Employee and his role in a company.
public class EmployeeRole{
    public int Id { set; get; }
    virtual public Employee Employee { set; get; }
    public string Role { set; get; }

    public EmployeeRole(Employee employee, string role){
        this.Employee = employee;
        this.Role = role;
    }
}

public class Employer{

    public string Name { set; get; }
    List<EmployeeRole> employees = new List<EmployeeRole>();
    virtual public List<EmployeeRole> Employees { get { return this.employees; } }

    public Employer(string name, Employee creator){
        this.Name = name;
        this.Employees.Add(new EmployeeRole(creator, "Creator"));
        creator.Employer = this;
    }
}

看起來很簡單。 沒有為DbContext中的那些類做任何特定配置。

但是,當我運行以下代碼時

using (DbContext db = DbContext.GetNewDbContext()){

    Employee creator = new Employee("Bob");
    db.Employees.Add(creator);
    db.SaveChanges();

    Employer employer = new Employer("employer", creator);
    db.Employers.Add(employer);
    db.SaveChanges();
   // I know I can call SaveChanges once (and it actually works in this case), 
   // but I want to make sure this would work with saved entities.
}

它拋出以下異常:

收集被修改; 枚舉操作可能無法執行。

堆棧跟蹤:

在System.Collections.Generic.List的System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource資源)中System.Collections.Generic.List的1.Enumerator.MoveNextRare() at System.Collections.Generic.List System.Data.Objects.ObjectStateManager.PerformAdd的1.Enumerator.MoveNext() (IList 1 entries)
at System.Data.Objects.ObjectStateManager.AlignChangesInRelationships(IList
1 entries)
at System.Data.Objects.ObjectStateManager.AlignChangesInRelationships(IList
1 entries)
at System.Data.Objects.ObjectStateManager.AlignChangesInRelationships(IList
處的System.Data.Objects.ObjectConManager.DetectChanges() 1 entries)
at System.Data.Objects.ObjectStateManager.AlignChangesInRelationships(IList
1條目)處的System.Data.Objects.ObjectStateManager.DetectChanges()處。 System.Data.Entity.Internal.Linq.InternalSet中的System.Data.Entity.Internal.Linq.InternalSet 1.ActOnSet(Action action, EntityState newState, Object entity, String methodName) at System.Data.Entity.Internal.Linq.InternalSet DetectChanges(布爾強制) 1.ActOnSet(Action action, EntityState newState, Object entity, String methodName) at System.Data.Entity.Internal.Linq.InternalSet (Object實體)

在System.Data.Entity.DbSet`1.Add(TEntity實體)

任何人都知道發生了什么,也許是如何解決它? 謝謝 !

對我來說,這看起來像是Entity Framework中的一個錯誤。 我把你的例子簡化為一個更簡單的例子,但結構相同:

public class TestA // corresponds to your Employee
{
    public int Id { get; set; }
    public TestB TestB { get; set; } // your Employer
}

public class TestB // your Employer
{
    public TestB()
    {
        TestCs = new List<TestC>();
    }

    public int Id { get; set; }
    public ICollection<TestC> TestCs { get; set; } // your EmployeeRoles
}

public class TestC // your EmployeeRole
{
    public int Id { get; set; }
    public TestA TestA { get; set; } // your Employee
}

這些是具有循環關系的三個實體:

TestA -> TestB -> TestC -> TestA

如果我現在使用與你的結構相同的相應代碼,我會得到相同的異常:

var testA = new TestA();
var testB = new TestB();
var testC = new TestC();

context.TestAs.Add(testA);

testA.TestB = testB;
testB.TestCs.Add(testC);
testC.TestA = testA;

context.ChangeTracker.DetectChanges();

請注意,我使用了DetectChanges而不是SaveChanges因為異常中的堆棧跟蹤清楚地表明實際上DetectChanges導致異常(由SaveChanges內部調用)。 我還發現調用SaveChanges兩次不是問題。 這里的問題只是在整個對象圖完成之前向上下文添加“早期”。

被修改的集合(作為例外是抱怨) 不是模型中的TestB.TestCs集合。 它似乎是ObjectStateManager的條目集合。 我可以通過在TestB類中用TestC TestC的單個引用替換ICollection<TestC> TestCs來驗證這一點。 這樣,模型根本不包含任何集合,但它仍然會針對修改后的集合拋出相同的異常。 (盡管有三個單引用, SaveChanges會失敗,因為EF不知道由於循環而以哪種順序保存實體。但這是另一個問題。)

我認為這是一個錯誤,EF更改檢測( DetectChanges )似乎修改了它自己的內部集合,它正在迭代。

現在,解決這個問題的方法很簡單:在調用SaveChanges之前,只需Add實體Add到上下文中作為最后一步:

var testA = new TestA();
var testB = new TestB();
var testC = new TestC();

testA.TestB = testB;
testB.TestCs.Add(testC);
testC.TestA = testA;

context.TestAs.Add(testA);

context.ChangeTracker.DetectChanges();

EF將整個相關對象圖添加到上下文中。 此代碼成功(也使用SaveChanges而不是DetectChanges )。

或者你的例子:

using (DbContext db = DbContext.GetNewDbContext()){
    Employee creator = new Employee("Bob");
    Employer employer = new Employer("employer", creator);

    db.Employees.Add(creator);
    db.SaveChanges();
}

編輯

這是相同的異常: 當使用可觀察集合時,實體框架拋出“集合被修改” 遵循該示例中的代碼情況類似:向上下文添加實體,然后更改/添加與該實體的關系。

EDIT2

有趣的是,這引發了同樣的異常:

var testA = context.TestAs.Find(1); // assuming there is already one in the DB
var testB = new TestB();
var testC = new TestC();

testA.TestB = testB;
testB.TestCs.Add(testC);
testC.TestA = testA;

context.SaveChanges(); // or DetectChanges, it doesn't matter

所以,我想將新實體的關系添加到現有實體中。 解決這個問題似乎不太明顯。

我有同樣的問題。 它看起來像EF中的一個錯誤。

我將代碼更改為在將實體設置為任何其他實體屬性之前將實體顯式添加到EF上下文。

我最近才遇到這個問題。 我發現EF討厭間接循環引用。 根據你的情況, 似乎雇主應該對自己員工的關系。 因此,從員工班中取出參考給雇主。

我今天早上遇到了同樣的問題,在我的情況下,我有一個以循環關系定義的“員工 - 經理”協會。 例如:

public class Employee 
{
    public string Name { set; get; }
    virtual public Employee Manager { set; get; }

    public Employee()
    {

    }
}

設置Manager屬性時,應用程序因上述錯誤而崩潰。 最后,結果是Employee類中的GetHashCode()方法的錯誤實現 由於實體之間的比較失敗,EF似乎無法發現修改后的實體; 因此,EF認為該集合已被修改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM