繁体   English   中英

使用 ADO.NET 异步调用 Oracle DB

[英]Asynchronous calls to Oracle DB using ADO.NET

我正在尝试使用 .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
            }
        });
    }

asyncawait用于异步代码。 通常,如果您有一个可扩展的数据库,您可以使您的 db 调用异步,从而扩展您的服务器。 请注意,ASP.NET 上async的主要好处是可伸缩性,而不是响应时间。

但是,正如其他人所指出的,Oracle 不支持异步代码。

但这并不重要,因为您发布的代码实际上并不是异步的 这就是我所说的“假异步”,因为它只是使用Task.Run而不是使用自然异步 API 将同步工作推送到后台线程。 (但如前所述,在这种情况下(即 Oracle),您没有任何自然异步的 API 可以使用)。

所以,你最终得到的是parallelism ,而不是asynchrony 特别是,代码将自己分散到 5 个线程池线程上来完成它的工作。

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

我发现绝大多数情况下,答案是“不,我不想让我的整个数据库服务器因这个请求而瘫痪”——换句话说,避免服务器上的并行性。

但是,如果您已经权衡了选项并决定是的,您的情况是在 ASP.NET 上适合并行的罕见情况之一,那么您应该问您在此处发布的问题:为什么这些是按顺序运行而不是同时运行 (旁注:这里是顺序vs并发,而不是同步vs异步

回答:我不知道。

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

也就是说,如果您想并行化您的 Web 服务器。 这是一个很大的“如果”。

要跟进有关 Oracle 异步实现的其他答案(没有足够的声誉来评论),Oracle 的异步方法并不是真正的异步,只是在幕后调用同步方法,因此调用它们的性能比同步方法差。

您可以观看https://github.com/oracle/dotnet-db-samples/issues/144以查看它们是否会提供真正的异步实现。 截至 2021 年第三季度,Oracle .NET 团队表示“也许以后再说”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM