錯誤一:
程序完整報錯:
A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext, however instance members are not guaranteed to be thread safe. This could also be caused by a nested query being evaluated on the client, if this is the case rewrite the query avoiding nested invocations.
中文翻譯:
在上一個操作完成之前,在此上下文上啟動了第二個操作。這通常是由使用同一DbContext實例的不同線程造成的,但是實例成員不能保證線程安全。這也可能是由於在客戶機上計算的嵌套查詢造成的,如果是這種情況,請重寫查詢以避免嵌套調用。
出現這個問題的原因是,我的數據庫注入用的是單例模式,然后我在一個異步方法里用Task.Factory.StartNew開啟了一個新線程,然后在這個新線程里操作了數據庫。之后就發現這個錯了。
解決辦法:
1、避免在新開啟的線程里操作數據庫,可以單獨封裝方法然后通過返回值的方式去做一些處理。
2、重新New一個上下文
var optionsBuilder = new DbContextOptionsBuilder<SqlContext>(); optionsBuilder.UseSqlite(Configuration.GetConnectionString("Sqlite")); using (var context = new SqlContext(optionsBuilder.Options)) { //操作數據庫的時候用context去保存 }
錯誤二:
完整錯誤:
Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'SqlContext'.
中文翻譯:
無法訪問已釋放的對象。此錯誤的一個常見原因是釋放從依賴項注入解析的上下文,然后稍后嘗試在應用程序的其他位置使用相同的上下文實例。如果對上下文調用Dispose()或在using語句中包裝上下文,則可能會發生這種情況。如果使用依賴項注入,則應讓依賴項注入容器負責處理上下文實例。
對象名:“SqlContext”。
出現這個問題的原因是,發現第一個錯誤之后,我想那我不注入單例注入成別的類型不就好了,然后下面的錯誤就誕生了。其實還是和我在一個異步方法里用Task.Factory.StartNew開啟了一個新線程,然后在這個新線程里操作了數據庫有關。
解決辦法:
既然說上下文釋放了那我再New一個好了,和上面的解決辦法一樣。
var optionsBuilder = new DbContextOptionsBuilder<SqlContext>();
optionsBuilder.UseSqlite(Configuration.GetConnectionString("Sqlite")); using (var context = new SqlContext(optionsBuilder.Options)) { //操作數據庫的時候用context去保存 }
這兩種錯誤的發生,其實最終的解決方案就是不要在新開的線程里操作數據庫,盡量避免就行了,就不用特殊處理了。
——————————————————————————————————————————————————————————
最近新做的項目,這個問題又出現了,這里補充一下
錯誤三:當數據量大的時候,連接持續時間太長也會被回收
我操作數據量特別大的時候,保存的時候報錯,連接被釋放了,沒辦法重新創建上下文一個好了,辦法同上。
var optionsBuilder = new DbContextOptionsBuilder<SqlContext>(); optionsBuilder.UseSqlite(Configuration.GetConnectionString("Sqlite")); using (var context = new SqlContext(optionsBuilder.Options)) { //操作數據庫的時候用context去保存 }