首页 > 解决方案 > .Net 应用程序中的异步任务和多线程与 SQL Server 集成

问题描述

问题描述:我正在开发一个带有 SQL Server 交互的 .Net 应用程序。这意味着最终用户能够从应用程序在 SQL Server 端创建/更新/删除条目。

最近,我在尝试我的应用程序时意识到 UI 停止了几秒钟,直到应用程序和 SQL Server 之间的事务完成,然后 UI 再次开始工作。当然,这对最终用户来说不是一个好的场景。所以我开始在我的应用程序中应用多线程,但我意识到在保存过程完成之前我无法提供对表单的访问。

例如:一个带有一个 TextEdit 控件的表单,最终用户在其中输入他的名字和另一个 TextEdit 控件,最终用户在其中输入他的电话号码,然后他点击了保存按钮。从我的应用程序中保存的 SQL 是

' Variable that holds the row number of the saved username
Dim SavedID as integer

' saving the username to the users table
SavedID = SQLControl.ExecScalar(String.format("INSERT INTO TABLE1 VALUES ({0});)", _
TextEdit1.text))

' saving the user phone number to the phone numbers table
SQLControl.ExecNonQuery(String.format("INSERT INTO TABLE2 VALUES ({0}, {1});)", _
SavedID, TextEdit2.text))

这意味着最终用户在保存完成之前不应具有访问权限,因为如果他在执行第二个之前具有访问权限SQLNonQuery,则数据可能会混乱。

PS:SQLControl.ExecScalar 和 SQLControl.ExecNonQuery 是自定义的子例程。

PS:我已经将参数应用于我的代码,但此代码仅用于描述我需要找到解决方案的问题。

问题:如果我需要应用异步任务将数据保存到 SQL Server,那么处理这种情况的最佳做法是什么?

标签: .netsql-servervb.netmultithreadingtask

解决方案


一些东西:

  1. 您在 UI 和数据库到 UI 之间进行编排,然后再返回到数据库。至少从您的代码中可以看出,这不是必需的,并且会导致不必要的网络延迟、性能不佳并且根本无法处理故障情况。尝试批量调用数据库,例如将 TextEdit1.Text 和 TextEdit2.Text 传递给单个存储过程或数据库调用,并在需要时返回 SavedID。

    1. 您并没有真正遵循任何分层或分层模式。查看存储库模式并确保您了解 SRP(单一责任原则)。UI 仅用于表示逻辑,而不用于进行数据库调用。

    2. 正如其他人在此处发布的那样,您正在向 SQL 注入攻击开放您的应用程序。这是一个重大的安全风险。

    3. 你不需要多线程。不过,您可以从 async/TPL 中受益。查看 ADO.NET 异步库 - ExecuteReaderAsync、ExecuteScalarAsync、ExecuteNonReaderAsync:https ://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.executereaderasync?view=netframework-4.7.2

    4. 异步允许您使用单个线程并行完成任务。这将使您的 UI 在后台 SQL 任务完成时响应。


推荐阅读