[英]How to solve "there is already an open datareader associated with this connection"
主要問題是,當 Web 應用程序啟動到 Internet 時,當負載很高時會引發異常,表明已經打開了數據讀取器。
以下是我們使用的規格:
有沒有辦法在沒有using(){}
塊的情況下解決這個問題? 這種方法的主要問題是,當關閉 using 塊時,我無法在 html 視圖中擴展 entityframework 對象的外鍵關系。
我還附上了一些源代碼,展示了我們如何在整個應用程序中保持單個數據庫上下文
public abstract class AbstractService
{
public Entities db_model
{
get
{
return DbContext.Instance.db_model;
}
}
}
public class DbContext
{
public Entities db_model = new Entities();
private static DbContext _dbContext;
public static DbContext Instance
{
get
{
if(_dbContext == null)
{
_dbContext = new DbContext();
}
return _dbContext;
}
}
}
此答案與有關在 ASP.NET 視圖中使用加載的實體的問題中提到的問題特別相關。 該問題詢問了一種無需using
塊或處理DbContext
即可解決此問題的using
,但是我建議完全這樣做。
原因是通常不希望在 ASP.NET 視圖中使用實體框架對象,因為這些對象不僅僅是普通的 POCO 對象; 它們隱藏了允許它們充當底層數據庫代理的邏輯,因此它們對創建它們的DbContext
的狀態具有隱藏的依賴性。
這是一個人為的示例,使用 EF 模型為Employee
和Department
與DbContext
:
public class CompanyDbContext : DbContext
{
public DbSet<Department> Departments { get; set; }
public DbSet<Employee> Employees { get; set; }
}
public class Department
{
public long Id { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
public class Employee
{
public long Id { get; set; }
public long DepartmentId { get; set; }
public virtual Department Department { get; set; }
}
如果在 ASP.NET 應用程序中使用這些,我將創建一些與實體框架無關的單獨模型,供 ASP.NET 使用。 例如:
public class DepartmentModel
{
public long Id { get; set; }
public List<EmployeeModel> Employees { get; set; }
}
public class EmployeeModel
{
public long Id { get; set; }
public long DepartmentId { get; set; }
}
幾點考慮:
根據 MSDN 文檔, “ DbContext
表示 UnitOfWork 和存儲庫模式的組合” - https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.dbcontext?redirectedfrom=MSDN&view= entity-framework-6.2.0 - 因此DbContext
應該盡可能短。
從上下文加載數據時,可以使用DbSet<>.Include()
檢索相關實體 - https://docs.microsoft.com/en-us/ef/ef6/querying/related-data
一般來說,將“數據”層與“視圖”層分離是有意義的 - 出於各種原因,其中一些列在此處: https : //docs.microsoft.com/en-us/aspnet /web-api/overview/data/using-web-api-with-entity-framework/part- 5——這涉及EF對象和POCO模型之間的映射。
用於查詢DbContext
的邏輯將使用 EF 查詢數據,並使用 POCO 模型返回該數據,以便只有直接處理DbContext
邏輯才與 EF 對象有關。 例如:
public List<DepartmentModel> GetAllDepartments()
{
using (var ctx = new CompanyDbContext())
{
// Ensure that related data is loaded
var departments = ctx.Departments
.Include(d => d.Employees);
// Manual mapping by converting into a new set of models to be used by the Views
var models = departments
.Select(d => new DepartmentModel
{
Id = d.Id,
Employees = d.Employees
.Select(e => new EmployeeModel
{
Id = e.Id,
DepartmentId = e.DepartmentId
})
.ToList(),
})
.ToList();
return models;
}
}
能夠使用這些 POCO 模型,同時需要一些額外的樣板代碼,提供了DbContext
和 ASP.NET 之間的完全分離,允許在 ASP.NET 視圖/控制器不關心DbContext
的生命周期或狀態的情況下使用DbContext
。
有時這看起來好像這種方法違反了“DRY”原則,但是我要指出 EF 對象和 ViewModel 對象的存在是為了解決不同的問題,並且 ViewModel 對象采用不同的形狀,甚至要求不適合添加到 EF 類的其他字段/屬性。
最后,上面使用了“手動”映射,但如果映射真的簡單明了,那么使用 AutoMapper 會更有意義: Cleanest Way To Map Entity To DTO With Linq Select?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.