使用Async/Await和EntityFramework调用多个存储过程

Zwa*_*wan 9 c# asynchronous stored-procedures entity-framework async-await

我必须调用多个消耗时间的存储过程.理想情况下,这些程序必须在同一时间执行,但它会引发很多问题.

这是简化的代码:

private  async void refresh_Controle(object sender, RoutedEventArgs e)
{
    SqlParameter param1 = new SqlParameter("@devicename", DeviceName);
    Task<int> mcResult = GenkaiBase.Database.ExecuteSqlCommandAsync("exec Refresh_McAfee @devicename", param1);
    int Mc = await mcResult;

    SqlParameter param2 = new SqlParameter("@devicename", DeviceName);

    Task<int> dcaiResult = GenkaiBase.Database.ExecuteSqlCommandAsync("exec Refresh_DCAI @devicename", param2);
    int Dc = await dcaiResult;
}
Run Code Online (Sandbox Code Playgroud)

这有两个问题:

  1. 那些程序一个接一个地执行
  2. 如果我不止一次调用它,我会得到一个SQL Server错误,其中一个过程被选为受害者.

我尝试在异步方法中使用此代码同时调用这两个过程:

public async Task<bool> Refresh_Control(string devicename)
{
    List<Task> Tlist = new List<Task>();
    Console.WriteLine("Launch Refresh");

    SqlParameter param1 = new SqlParameter("@devicename", devicename);

    Task<int> mcResult =  Genkai_db.Database.ExecuteSqlCommandAsync("exec Refresh_McAfee @devicename", param1);

    SqlParameter param2 = new SqlParameter("@devicename", devicename);

    Task<int> dcaiResult =  Genkai_db.Database.ExecuteSqlCommandAsync("exec Refresh_DCAI @devicename", param2);

    Console.WriteLine("all set");

    Tlist.Add(mcResult);
    Tlist.Add(dcaiResult);

    await Task.WhenAll(Tlist.ToArray());
    int mc = await mcResult;
    int dc = await dcaiResult;

    Console.WriteLine("Finish Refresh" + mc + dc);
    return true;
}
Run Code Online (Sandbox Code Playgroud)

逻辑适用于发送事物同时但第二个过程抛出错误导致第一个尚未完成.

由goole翻译错误:

EntityFramework.dll中出现"System.NotSupportedException"类型的异常,但未在用户代码中处理

附加信息:在上一个异步操作完成之前,在此上下文中启动了第二个操作.使用"await"确保在此上下文中调用另一个方法之前完成所有异步操作.没有任何成员实例保证是线程安全的.

那么什么是交易,为什么我不能同时调用几个存储过程而不被SQL Server卡住?

Dav*_*ine 7

更新

我认为EF目前根本不支持这一点,也许这是基于这个SO答案的重复问题.它不能做...抱歉.

原版的

问题是你要await两次尝试.当你将它们传递给await Task.WhenAll函数时,它们并行运行并等待着.然后,您将尝试再次等待它们,而不是访问.Result任务实例.

请尝试下面的代码,让我知道它是否有效.

public async Task Refresh_Control(string devicename)
{
    Task<int> mcResult = 
        Genkai_db.Database.ExecuteSqlCommandAsync("exec Refresh_McAfee @devicename", 
            new SqlParameter("@devicename", devicename));
    Task<int> dcaiResult = 
        Genkai_db.Database.ExecuteSqlCommandAsync("exec Refresh_DCAI @devicename", 
            new SqlParameter("@devicename", devicename));

    await Task.WhenAll(mcResult, dcaiResult);

    int mc = mcResult.Result;
    int dc = dcaiResult.Result;

    Console.WriteLine("Finish Refresh :: mc=" + mc + ", dc=" + dc);
}
Run Code Online (Sandbox Code Playgroud)