【问题标题】:Call multiple stored procedures using Async/Await and EntityFramework使用 Async/Await 和 EntityFramework 调用多个存储过程
【发布时间】:2015-12-08 13:27:50
【问题描述】:

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

这是简化的代码:

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;
}

这有两个问题:

  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;
}

逻辑可以同时发送,但第二个过程会引发错误,因为第一个尚未完成。

goole 翻译错误:

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

附加信息:在此上下文中启动了第二个操作 在之前的异步操作完成之前。采用 “等待”以确保所有异步操作都已完成 在此上下文中调用另一个方法之前。没有成员实例 保证是线程安全的。

那么问题是什么,为什么我不能同时调用多个存储过程而不会被 SQL Server 卡住?

【问题讨论】:

  • 实体框架你不能,你可以用多个上下文,但我想你可以用普通的 ADO.NET 做到这一点

标签: c# entity-framework stored-procedures asynchronous async-await


【解决方案1】:

更新

我相信 EF 目前根本不支持这一点,也许这是基于this SO answer 的重复问题。做不到……对不起。

原创

问题是您尝试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);
}

【讨论】:

  • 它引发了与我在以 Task dcaiResult = 开头的第二个示例相同的错误。 (请参阅主帖中的错误)。一个 cmd 已经启动,我必须在执行第二个之前等待???
  • await 不运行任务,它等待已经运行的任务。当时 Task.WhenAll 是 hin 两个任务都已经在运行。
  • 是的,错误不在执行第二个过程的等待行上。它拒绝执行的以太EF或SQL服务器。但我怀疑它没有解决这个问题。
  • @David 您确认了它的 EF 限制,所以意味着我可以与 ADO 并行?我知道它也会引发 sql 问题,但如果我只需要处理死锁而不是这个限制,那么使用 ADO 可能会更好。
猜你喜欢
  • 2016-01-15
  • 2019-06-08
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 1970-01-01
  • 1970-01-01
  • 2015-04-06
相关资源
最近更新 更多