>问题描述:我正在开发一个具有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,那么处理此类情况的最佳做法是什么?
几件事:
-
你正在 UI 和数据库到 UI 之间协调,然后再回到数据库。至少从代码中很明显的情况来看,这是不需要的,并且会导致不必要的网络延迟、性能不佳,并且根本无法处理故障场景。尝试对数据库的调用进行批处理,例如将 TextEdit1.Text 和 TextEdit2.Text 传递给单个存储过程或数据库调用,并在需要时返回 SavedID。
-
你并没有真正遵循任何分层或分层的模式。查看存储库模式,并确保您了解 SRP(单一责任原则(。UI 仅用于表示逻辑,而不用于进行数据库调用。
-
正如其他人在这里发布的那样,您正在向SQL注入攻击开放应用程序。这是一个重大的安全风险。
-
您不需要多线程。不过,您可以从异步/TPL中受益。查看 ADO.NET 异步库 - ExecuteReaderAsync,ExecuteScalarAsync,ExecuteNonReaderAsync : https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.executereaderasync?view=netframework-4.7.2
-
异步允许您使用单个线程并行完成操作。这将使您的 UI 在后台 SQL 任务完成时响应。
-