2011-09-24 43 views
14

在過去的2天裏,這一直讓我瘋狂。 我有3個很基本的類(當然,減少可讀性)EF 4.1和「集合被修改;枚舉操作可能無法執行」。例外

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.ThrowHelper.ThrowInvalidOperationException(ExceptionResource 資源)維持在 System.Data.Objects System.Collections.Generic.List 1.Enumerator.MoveNextRare() at System.Collections.Generic.List 1.Enumerator.MoveNext() .ObjectStateManager.PerformAdd(IList entries)at System.Data.Objects.ObjectStateManager.DetectChanges() at System.Data.Objects.ObjectContext.DetectChanges()at System.Data.Entity.Internal.InternalContext.Dete ctChanges(布爾 力)在 System.Data.Entity.Internal.Linq.InternalSet 1.ActOnSet(Action action, EntityState newState, Object entity, String methodName) at System.Data.Entity.Internal.Linq.InternalSet 1.增加(對象實體)
在System.Data.Entity.DbSet`1.Add(TEntity實體)

任何人有一個想法是怎麼回事,也許如何解決它? 謝謝!

+1

您在'僱主'級擁有'僱員'屬性和'列表<僱員角色'!沒有其他信息,他們不能映射到一起。請在這裏留下完整的代碼或更多解釋您的目的。或者你可以在這裏上傳數據庫模式的屏幕截圖嗎? –

+0

http://social.msdn.microsoft.com/Forums/en-US/1a49f75d-5168-4829-95f8-02eae38a3ee3/entityframework-41-exception-collection-was-modified-enumeration-operation-may-not-execute – Mohsen

回答

2

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

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

+2

你能解釋一下你到底做了什麼嗎? –

16

對我來說,這看起來像一個實體框架中的錯誤。我的例子煮制過一種簡單但具有相同的結構:

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)似乎修改它自己的內部集合,它只是迭代。現在

,修復這個問題非常簡單:只需Add實體上下文作爲最後一步,你叫SaveChanges前:

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

編輯

這是同樣的異常:Entity Framework throws "Collection was modified" when using observable collection。遵循該示例中的代碼,情況類似:將實體添加到上下文,然後更改/添加關係到該實體。

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 

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

+0

任何後續的這一個。看來我有同樣的問題。有什麼解決辦法嗎?我非常需要將現有數據添加到新實例。它是否被添加爲一個錯誤? – Michael

+0

@邁克爾:不,從我這邊來看,這不是什麼新鮮事。 – Slauma

+0

我也有這個問題,需要修復 – JarrettV

2

我剛剛自己遇到了這個問題。我發現,EF不喜歡間接循環引用。在你的情況下,它似乎僱主應該擁有與員工的關係。因此,從僱員階層中將參考資料提供給僱主。

0

今天早上我遇到了同樣的問題,在我的情況下,我有一個用循環關係定義的「Employee-Manager」關聯。例如:

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

    public Employee() 
    { 

    } 
} 

設置管理器屬性時,應用程序崩潰時出現上述錯誤。最後竟然是Employee類中GetHashCode()方法的執行錯誤。由於實體之間的比較失敗,EF似乎無法發現修改後的實體;因此,EF認爲該收藏已被修改。

相關問題