2014-02-14 100 views
1

我使用實體框架(DbContext),UnitOfWork和存儲庫模式編寫了一個小應用程序。下面的代碼實體框架 - 如何避免命令不同步異常

using (IUnitOfWork testUow = uowFactory.CreateUnitOfWork()) 
{ 
    foreach (Transponder transp in testUow.Transponders.GetAll()) // outer sql 
    { 
     var query = testUow.Animals.GetAll() 
        .Where(anim => anim.TransponderId == transp.Id); // inner sql 

     // next line throws EntityCommandException: 
     Animal test = query.Single(); 
    } 
} 

產生

EntityCommandException: {"Commands out of sync; You can't run this command now"}

TranspondersAnimals是我的倉庫。

爲什麼我會得到這個異常?

有沒有像我的例子(在代碼示例中標記爲內部和外部的SQL)產生嵌套的SQL命令的代碼是好的。

如何更改我的代碼/設計以避免此異常?

我知道我可以重寫linq查詢,所以它是一個工作班次,但我對更通用的解決方案感興趣。

回答

1

MySql(連接器)不支持多個活動結果集(MARS)。因此,在執行外部查詢(在循環迭代時運行)時,它無法通過同一連接讀取其他結果集。

因此,正如你所說,重寫查詢是解決方案。無論如何,這是更好的,因爲你在這裏遇到了1 + N問題。

+0

所以設計本身是正確的,我只需要避免MARS?但是,如果我的工作單元有很長的使用壽命(如與視圖模型共享生命時間),那麼在同一連接上將會有許多查詢。那我該如何避免MARS? –

+0

你能解釋一下1 + N的問題嗎?謝謝你的幫助! –

+0

N + 1是反模式,其中1個查詢觸發N個查詢來提取相關對象,而一個連接可以全部在一個查詢中進行。通常稱它爲N + 1,而不是1 + N,不知道爲什麼。至於MARS問題,我認爲你應該避免延遲加載,因爲這會在擁有對象被讀取時觸發查詢。但總的來說,減少上下文的壽命是個好主意。 –