2015-12-15 21 views
3

我試圖做以相同的DbContext第二個電話會導致錯誤「的DbContext已配置」

public void SomeTestMethod(){ 
    var person = this.PersonManager.Get(new Guid("someguid")); 

    person.Lastname = "Jameson"; 

    this.PersonManager.Save(person); // This goes wrong 
} 

如果它出錯

上述保存方法調用的代碼:

protected void Add<T>(T source, MyEntities context, bool isNew) where T : class 
{ 
    if (isNew) 
    { 
     context.Set<T>().Add(source); 
    } 
    else 
    { 
     var entry = context.Entry(source); 
     if (entry.State == EntityState.Detached) 
     { 
      context.Set<T>().Attach(source); 

      entry.State = EntityState.Modified; 
     } 
    } 
} 

var entry = context.Entry(source);行是導致此錯誤的行:

The operation cannot be completed because the DbContext has been disposed.

我見過的回答到,建議使用.ToList()(或別的東西來執行的鏈接)類似的問題,但是這已經發生了,因爲Get返回一個DTO對象。

一些背景

PersonManager在保存時,使用此設置的DbContext:

var context = new MyEntities(); 
this.PersonRepository = repositoryProvider.GetRepositoryByType<PersonRepository>(context); 

var context = new MyEntities();只是爲了得到它現在的工作,這將是DI注入。

而這又取決於這一點:

public T GetRepositoryByType<T>(MyEntities context) where T : IContextDependent 
{ 
    var instance = this.Repositories.SingleOrDefault(x => x is T); 

    instance.SetContext(context); 

    return (T)instance; 
} 

由於使用了相同的PersonManager,事實上同PersonRepository用於(並因此同樣的情況下),所以不看看它爲什麼會在第二次電話中處理。

+0

你的Get和Save都使用'PersonRepository'嗎? –

+0

@AlexanderDerck:正確,由運行它們的'PersonManager'提供。 – Spikee

回答

3

你還沒有給出你創建你的上下文的地方,但我假設它在一個方法中,也許是構造函數。你的上下文被限制在那個方法中,所以當方法調用結束時,GC可以自由處理它。我認爲,即使只有一次,它都可以工作的事實是,在垃圾收集之前,你已經設法擊中它。

具有諷刺意味的是,你的問題正在發生,因爲你還沒有使用DI。簡單地注入就足以解決問題。至少,您的背景應與PersonManager的範圍相同。

+0

正確,我正在使用構造函數注入。請參閱關於DI的更新。 – Spikee

+0

GC永遠不會直接調用'.Dispose()'。 GC可能會調用一個終結器,並可能會顯式調用'.Dispose()',但在大多數情況下,GC不會觸發dispose。 – Enigmativity

+0

@Enigmativity:我沒有字面上的意思。我只是意味着上下文最終由GC的工作處理,不一定GC實際上稱之爲「Dispose」。 –