EF上的数据库连接错误
本文关键字:错误 数据库连接 EF | 更新日期: 2023-09-27 18:01:00
我对实体框架很陌生,我正在编写的一个基于web api的网站(连接到mssql(遇到了问题。我不断收到看似随机的错误(大部分似乎与数据库有关(。这些错误通常发生在网站首次发布时,但有时也会发生在距离上次发布数小时后。错误选择:
- 无效操作。连接已关闭
- 已经有一个打开的DataReader与此命令关联,必须先关闭它
- 连接未关闭。连接的当前状态为正在连接
- 创建模型时无法查看上下文
- 基础提供程序无法打开
我的上下文如下:
public class Context : DbContext
{
public Context() : base("name=DefaultConnection")
{
}
public override int SaveChanges()
{
DateTime now = DateTime.Now;
foreach (ObjectStateEntry entry in (this as IObjectContextAdapter).ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
{
if (!entry.IsRelationship)
{
IHasUpdated updated = entry.Entity as IHasUpdated;
if (updated != null)
updated.updated = now;
}
}
return base.SaveChanges();
}
public DbSet<Branch> Branches { get; set; }
public DbSet<Company> Companies { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<UsefulLink> UsefulLinks { get; set; }
}
DbSet比这个多得多。我应该为每一个创建一个单独的上下文吗?
我的一个基本控制器:
public class UsefulLinksController : ApiController
{
private Context db = new Context();
[ResponseType(typeof(UsefulLinksWrapper))]
public IHttpActionResult GetUsefulLinks([FromUri]UsefulLinkParams prams)
{
UsefulLinksWrapper wrapper = new UsefulLinksWrapper();
Meta meta = new Meta();
IQueryable<UsefulLink> query = db.UsefulLinks;
if (prams.sortBy == null)
{
prams.sortBy = "ID";
}
// Paging
query = query.OrderBy(prams.sortBy + " " + prams.sortDirection).Skip(prams.offset - 1).Take(prams.limit);
List<UsefulLink> data = query.ToList();
meta.totalCount = query.Count();
meta.offset = 1;
meta.limit = prams.limit;
wrapper.meta = meta;
wrapper.data = data;
return Ok(wrapper);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool UsefulLinkExists(int id)
{
return db.UsefulLinks.Count(e => e.ID == id) > 0;
}
}
当我在本地运行该网站时,我似乎没有看到这些错误,尽管当它发布时,我们中有两个人会点击它,所以这个问题可能源于多个用户?
Chris,我注意到在您的控制器中,您正在与控制器类中的所有方法共享数据库上下文。
这通常不是实体框架中的最佳实践(请参阅:EntityFramework 4 ObjectContext Lifetime(。你应该尽可能简短地保持你的语境。让上下文保持活动状态以在多个方法之间共享可能会导致上面列出的许多错误。
我建议尝试实例化上下文的一个新实例,不管它在哪里使用,并快速处理它
这通常会导致更稳定的行为。
所以下面是:
class SomeClass
{
private context = new Context(); //sharing your context with all methods
public someMethod()
{
context.doSomething;
}
public someMethod2()
{
context.doSomething;
}
}
应该变成:
class SomeClass
{
public someMethod()
{
Context context = new Context(); //now your context is declared and disposed of within each method
context.doSomething;
}
public someMethod2()
{
Context context = new Context(); //now your context is declared and disposed of within each method
context.doSomething;
}
}
或者更好的是,您可以使用using构造来确保您的上下文得到正确处理:
class SomeClass
{
public someMethod3()
{
using(Context context = new Context()) //now wrapping the context in a using to ensure it is disposed
{
context.doSomething;
}
}
}
我建议你尝试以上的改变,看看你的行为是否变得更加稳定。
由于我不知道您的页面是如何使用方法UsefulLinksController
以及按哪个顺序使用的,我认为UsefulLinkExists
可能是由于延迟加载造成的罪魁祸首
延迟加载意味着延迟相关数据的加载,直到特别要求
这就解释了为什么你的"读者"仍然是"开放的"。
尝试:
return db.UsefulLinks.ToList().Count(e => e.ID == id) > 0;
在任何情况下,您都可以在上下文构造函数中默认禁用延迟加载,如下所示:
public MyEntitiesContext() : base("name=MyEntitiesContext", "MyEntitiesContext")
{
this.ContextOptions.LazyLoadingEnabled = false;
OnContextCreated();
}
据我所知,它适用于EF4及以上。