使用ADO.NET异步调用Oracle DB

Cap*_*nRG 0 c# asp.net ado.net webforms async-await

我正在尝试使用异步和等待.NET Framework 4.5中提供的功能执行多个数据库调用.这是我第一次实现此功能.

如果每个查询花费7秒,则过去需要35秒(5个查询*7秒).通过以下实现,我期待它应该在接近7-9秒的时间内在asp页面中获取和填充控件.但是,它仍然需要35秒,证明了我的同步行为.

有人可以帮助我在下面的异步实现中出错.

我对任何投入表示赞赏,因为几天以来我一直在为此而烦恼

    protected void Page_Load(object sender, System.EventArgs e)
    {
        RegisterAsyncTask(new PageAsyncTask(FillControlsAsync));
    }

    public async Task FillControlsAsync()
    {
         Task[] tasks = new Task[]{
         PopulateControlTask(query1, "controlID1"),
         PopulateControlTask(query2, "controlID2"),
         PopulateControlTask(query3, "controlID3"),
         PopulateControlTask(query4, "controlID4"),
         PopulateControlTask(query5, "controlID5")
        });

        await Task.WhenAll(tasks);
    }
    public async Task PopulateControlTask(string query, string control)
    {
       await Task.Run(() =>
           {
               DataSet ds;
               OracleCommand cmd;
               OracleDataAdapter da;
               try
               {
                   if (!Page.IsPostBack)
                   {
                       cmd = new OracleCommand(query, cn);
                       da = new OracleDataAdapter(cmd);
                       ds = new DataSet();
                       da.Fill(ds);
                       switch (control)
                       {
                           case "controlID1":
                                //some custom code for control 1
                                // like attaching the datasource to control.
                               break;
                           case "controlID2":
                               //some custom code for control 2
                               break;
                            case "controlID2":
                            //some custom code for control 3
                            break;
                            case "controlID3":
                            //some custom code for control 4
                            break;
                            case "controlID4":
                            //some custom code for control 5
                            break;
                    }
                }
            }
            catch(Exception e)
            {
                 //some error handling here
            }
        });
    }
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 5

asyncawait用于异步代码.通常,如果您具有可伸缩的数据库,则可以使db调用异步,从而扩展服务器.请注意,asyncASP.NET 的主要优点是可伸缩性,而不是响应时间.

但是,正如其他人所说,Oracle不支持异步代码.

但这并不重要,因为你发布的代码实际上并不是异步的!这就是我所谓的"假异步",因为它只是将同步工作推送到后台线程Task.Run而不是使用自然异步API.(但正如已经指出的那样,在这种情况下(即Oracle),您没有任何自然异步API可供使用).

所以,你最终得到的是并行性,而不是异步性.特别是,代码正在通过5个线程池线程进行传播以完成其工作.

现在,您需要做的第一件事就是问问自己是否真的想在服务器上实现并行性.您的请求将采用5个线程而不是1个(或0).这可能会极大地影响Web服务器的可伸缩性(以一种糟糕的方式).另外,请考虑后端的功能.如果它是单个服务器并且这些查询都在单个硬盘驱动器上命中一个数据库,那么并行化其中5个实际上会产生任何好处,或者它实际上是否会因为磁盘争用而变坏?(您应该能够启动一个快速控制台应用程序来测试您的数据库如何响应串行与并行请求,空闲时和负载时).

我发现绝大多数时候,答案是"不,我不想让我的整个数据库服务器为这一个请求付出代价" - 换句话说,避免服务器上的并行性.

但是,如果你已经权衡了选项并且确定是,那么你的问题是并行性适用于ASP.NET的极少数情况之一,那么你应该问一下你在这里发布的问题:为什么这些顺序运行而不是同时运行(旁注:这是顺序 vs 并发,不是同步 vs 异步)

答:我不知道.

但我猜测:如果数据库连接(cn在您的代码片段中)是共享的,那么数据库连接本身可能一次仅限于一个查询.其他数据库连接系统也有类似的限制 我尝试的第一件事是给每个查询自己的连接.

也就是说,如果要并行化Web服务器.这是一个很大的 "如果".