我对实体框架非常陌生,我在编写基于 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;
}
}
当我在本地运行该网站时,我似乎没有看到这些错误,尽管在发布该网站时我们有两个人点击了它,所以问题可能源于多个用户?
克里斯,我注意到在您的控制器中,您正在与控制器类中的所有方法共享数据库上下文。
这通常不是实体框架中的最佳实践(请参阅:EntityFramework 4 ObjectContext 生命周期)。您应该尽可能简短地保持上下文的活力。让上下文保持活动状态以在多个方法之间共享可能会导致上面列出的许多错误。
我建议尝试实例化上下文的新实例,而不是在任何使用它的地方并快速处理它。
这通常会导致更稳定的行为。
所以如下:
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;
}
}
}
我建议尝试上述改变,看看你的行为是否变得更加稳定。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)