Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在不同上下文上重写为异步调用的同步dbcontext查询列表_C#_Entity Framework_Async Await - Fatal编程技术网

C# 在不同上下文上重写为异步调用的同步dbcontext查询列表

C# 在不同上下文上重写为异步调用的同步dbcontext查询列表,c#,entity-framework,async-await,C#,Entity Framework,Async Await,这篇文章是在使用实体框架版本6.2的背景下发表的 好的,我有一个相当慢的端点,基本上如下所示: public IHttpActionResult GetCounts() { int count1 = service.GetCount1(); int count2 = service.GetCount2(); Models.Counts ret = new Counts() { Count1

这篇文章是在使用实体框架版本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);
    }
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);
    }
对服务的每个调用都在同一个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 IHttpActionResult GetCounts()
    {
        int count1 = service.GetCount1();
        int count2 = service.GetCount2();

        Models.Counts ret = new Counts()
        {
            Count1 = count1,
            Count2 = count2,
        };

        return Ok(ret);
    }
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);
    }
公共异步任务GetCountsAsync() { var tcount1=service.GetCount1Async(); var tcount2=service.GetCount2Async(); 等待任务。WhenAll(t计数1,t计数2); int count1=t计数1.结果; int count2=t计数2.结果; Models.Counts ret=新计数() { Count1=Count1, Count2=Count2 }; 返回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();
       } 
    }
}
//在服务中
公务舱服务
{
公共服务()
{ 
} 
公共异步任务GetCount1()
{
使用(var context=new MyDbContext())
{ 
返回wait context.coll1.CountAsync();
}
}
公共异步任务GetCount2()
{
使用(var context=new MyDbContext())
{ 
返回wait context.coll2.CountAsync();
} 
}
}
这有什么坏处吗?它可以工作,并且无疑提高了查询的性能

我对线程(在本例中为异步/等待)相当陌生,因此不熟悉潜在的缺点,或者我上面提到的是反模式,但我的一部分感觉在使用EF的dbcontext时,这种结构可能会有问题??希望这只是我的无知造成的那种感觉

还要注意的是,我最初将上下文作为服务类的一个字段来重写服务;但是,最终得到了错误:

在上一个异步操作完成之前,在此上下文上启动了第二个操作。使用“await”确保在此上下文上调用另一个方法之前已完成任何异步操作。任何实例成员都不能保证线程安全


将上下文的生命周期更改为方法调用解决了这一问题,但看到这个错误,我对这个总体策略感到紧张。

在我看来,您这样做是正确的

  • 您不应该缓存
    DbContext
    ,sql连接已经为您缓存好了。这样做可能会导致您已经遇到的各种细微错误
  • 上下文不是线程安全的
  • 它们相当轻,所以性能不应该是一个真正的问题
  • 并且最好放在一个包含少量工作的using语句中
  • 总而言之,将每个
    GetCount
    放在一起似乎是最好的方法