本文是在使用Entity Framework版本6.2的上下文中。
好,所以我的端点相当慢,基本上是:
public IHttpActionResult GetCounts()
{
int count1 = service.GetCount1();
int count2 = service.GetCount2();
Models.Counts ret = new Counts()
{
Count1 = count1,
Count2 = count2,
};
return Ok(ret);
}
对服务的每次调用都在dbcontext的同一实例上执行:
//In the service
public class Service
{
private MyDbContext context;
public Service()
{
context = new MyDbContext();
}
public int GetCount1()
{
return context.coll1.Count();
}
public int GetCount2()
{
return context.coll2.Count();
}
}
最好将每个服务调用视为独立的工作单元,并为每个服务创建上下文,然后利用EF的异步方法,如下所示:
public async Task<IHttpActionResult> GetCountsAsync()
{
var tcount1 = service.GetCount1Async();
var tcount2 = service.GetCount2Async();
await Task.WhenAll(tcount1, tcount2);
int count1 = tcount1.Result;
int count2 = tcount2.Result;
Models.Counts ret = new Counts()
{
Count1 = count1,
Count2 = count2
};
return Ok(ret);
}
正在更改服务
//In the service
public class Service
{
public Service()
{
}
public async Task<int> GetCount1()
{
using(var context = new MyDbContext())
{
return await context.coll1.CountAsync();
}
}
public async Task<int> GetCount2()
{
using(var context = new MyDbContext())
{
return await context.coll2.CountAsync();
}
}
}
这有不利之处吗?它可以正常工作,并且绝对提高了查询性能。
我对线程处理(在这种情况下为异步/等待)比较陌生,因此对潜在的缺点不熟悉,或者如果我上面的内容是反模式的,但我的一部分感到使用EF的dbcontext时此结构可能存在问题??希望那只是我对这种感觉的无知。
还要注意,我最初使用上下文将服务重写为服务类的字段;但是,最终出现错误:
在先前的异步操作完成之前,第二个操作在此上下文上开始。使用“ await”来确保在此上下文上调用另一个方法之前,所有异步操作都已完成。不能保证任何实例成员都是线程安全的。
将上下文的生命周期更改为方法调用可以解决此问题,但是看到该错误通常会使我对这种通用策略感到不安。
答案 0 :(得分:1)
我认为您的做法正确,
DbContext
,sql连接已经为您缓存了。这样做会导致各种细微的错误,这些错误您已经遇到过。总之,将每个GetCount
放在这似乎是最好的方法