当前位置: 首页 > 编程语言 > C#

如何让两个SQL查询真正异步分享

时间:2023-04-10 11:37:42 C#

如何让两个SQL查询真正异步涉及线程的严肃编程,所以我的问题可能是缺乏对特定库的了解以及对异步在编程方面的真正含义的更普遍的误解。所以我的真实情况是这样的——我需要获取有关用户的数据。在我目前的情况下,它是财务数据,所以假设我需要特定用户的所有帐户、所有存款和所有委托。在我的例子中,这意味着为每个属性查询数百万条记录,并且每个查询本身都相对较慢,但是获取帐户比获取存款慢几倍。所以我为我将要使用的三种银行产品定义了三个类,当我想为某个用户获取所有银行产品的数据时,我会这样做:Listaccounts=GetAccountsForClient(intclientId);列出存款=GetDepositsForClient(intclientId);Listconsignations=GetConsignationsForClient(intclientId);所以问题从这里开始我需要同时获取所有三个列表,因为我要将它们传递到显示所有用户数据的视图。但就像现在一样,执行是同步的(如果我在这里正确使用该术语),所以为所有三种产品收集数据的总时间是:Total_Time=Time_To_Get_Accounts+Time_To_Get_Deposits+Time_To_Get_Consignations慢,所以总时间很长,而且帐户查询比其他两个查询花费更多的时间,所以今天我想到的是-“如果我可以同时执行此查询会怎样”。也许这是我对这个问题最大的误解,但对我来说最接近这个想法的是让它们异步,所以也许Total_Time不会是最慢查询的时间,但会比这三个加起来快得多。由于我的代码很复杂,所以我创建了一个简单的用例,我认为它很好地反映了我正在尝试做的事情。我有两种方法:publicstaticasyncTaskGetAccounts(){inttotal1=0;使用(SqlConnectionconnection=newSqlConnection(connString)){stringquery1="SELECTCOUNT(*)FROM[MyDb].[dbo].[Accounts]";SqlCommand命令=newSqlCommand(query1,connection);connection.Open();for(inti=0;i<19000000;i++){字符串s=i.ToString();}total1=(int)awaitcommand.ExecuteScalarAsync();Console.WriteLine(total1.ToString());}返回total1;}和第二种方法:publicstaticasyncTaskGetDeposits(){inttotal2=0;使用(SqlConnectionconnection=newSqlConnection(connString)){stringquery2="SELECTCOUNT(*)FROM[MyDb].[dbo].[Deposits]";SqlCommand命令=newSqlCommand(query2,connection);connection.Open();total2=(int)awaitcommand.ExecuteScalarAsync();Console.WriteLine(total2.ToString());}返回total2;}我称之为:staticvoidMain(string[]args){Console.WriteLine(GetAccounts().Result.ToString());控制台.WriteLine(GetDeposits().Result.ToString());正如您所看到的,我首先调用了GetAccounts()并故意减慢了执行速度,因此我有机会继续执行下一个方法,但我有一段时间没有得到任何结果,然后我在控制台上打印同一时间。所以问题-如何做到这一点,这样我就不必等待第一种方法完成,这样我就可以继续使用下一种方法。一般来说,代码结构并不重要,我真正想弄清楚的是是否有任何方法可以使两个查询同时执行。这里的示例是我研究的结果,可能会扩展到我会得到想要的结果的程度。PS我正在使用ExecuteScalarAsync();只是因为我开始使用一种正在使用它的方法。实际上我会使用Scalar和Reader。在尚未完成的任务上使用Result属性时,调用线程会阻??塞,直到操作完成。这意味着在您的情况下,GetAccounts操作需要在调用GetDeposits之前完成。如果要确保这些方法是并行的(包括同步CPU密集型部分),则需要将该工作卸载到另一个线程。最简单的方法是使用Task.Run:staticvoidMain(string[]args){varaccountTask=Task.Run(async()=>Console.WriteLine(awaitGetAccounts()));vardepositsTask=Task.Run(async()=>Console.WriteLine(awaitGetDeposits()));Task.WhenAll(accountTask,depositsTask).Wait();由于Main不能是异步的,所以不能使用await你可以简单地调用这个方法并同步等待它是使用Wait完成的。下面是异步和并行执行两个任务的方法:TaskaccountTask=GetAccounts();任务depositsTask=GetDeposits();int[]results=awaitTask.WhenAll(accountTask,depositsTask);intaccounts=结果[0];int存款=结果[1];我通常更喜欢使用Task.WaitAll。为了设置此代码段,我更改了GetAccounts/GetDeposits签名以仅返回整数(publicstaticintGetAccounts())我将Console.WriteLine放在与赋值返回相同的线程中,以在返回GetDeposits之前验证GetAccounts,但这不是必须的,最好移到Task.WaitAll之后。privatestaticvoidMain(string[]args){intgetAccountsTask=0;intgetDepositsTask=0;列表任务=newList(){Task.Factory.StartNew(()=>{getAccountsTask=GetAccounts();Console.WriteLine(getAccountsTask);}),Task.Factory.StartNew(()=>{getDepositsTask=GetDeposits();控制台.WriteLine(getDepositsTask);})};Task.WaitAll(tasks.ToArray());}如果是ASP。NET,在页面呈现后使用AJAX获取并存储数据。每个AJAX提取都是异步的。如果要同时在服务器上创建SQL查询?用法://添加一些查询,即。ThreadedQuery.NamedQuery([Name],[SQL])varnamedQueries=newThreadedQuery.NamedQuery[]{...};System.Data.DataSetds=ThreadedQuery.RunThreadedQuery("Server=foo;Database=bar;Trusted_Connection=True;",namedQueries).Result;字符串味精=字符串。空;foreach(System.Data.DataTablettinds.Tables)msg??+=string.Format("{0}:{1}rn",tt.TableName,tt.Rows.Count);资源:以上就是C#学习教程的全部内容:如何让两个SQL查询真正异步共享,如果对大家有用,需要进一步了解C#希望大家多多关注教程-公开课ThreadedQuery{publicclassNamedQuery{publicNamedQuery(stringTableName,stringSQL){this.TableName=TableName;这个.SQL=SQL;}publicstringTableName{get;放;}公共字符串SQL{得到;放;}}publicstaticasyncSystem.Threading.Tasks.TaskRunThreadedQuery(stringConnectionString,paramsNamedQuery[]queries){System.Data.DataSetdss=newSystem.Data.DataSet();列表>asyncQryList=new列表>();foreach(查询中的varqq)作为yncQryList.Add(fetchDataTable(qq,ConnectionString));foreach(vartskinasyncQryList){System.Data.DataTabletmp=awaittsk.ConfigureAwait(false);dss.Tables.Add(tmp);}返回dss;}privatestaticasyncSystem.Threading.Tasks.TaskfetchDataTable(NamedQueryqry,stringConnectionString){//创建连接,打开它并在连接上创建命令try{System.Data.DataTabledt=newSystem.Data.DataTable(qry.表名);使用(SqlConnectionconnection=newSqlConnection(ConnectionString)){awaitconnection.OpenAsync().ConfigureAwait(false);System.Diagnostics.Debug.WriteLine("连接打开..."+qry.TableName);using(SqlCommandcommand=newSqlCommand(qry.SQL,connection)){using(SqlDataReaderreader=command.ExecuteReader()){System.Diagnostics.Debug.WriteLine("查询执行..."+qry.TableName);dt.Load(阅读器);System.Diagnostics.Debug.WriteLine(string.Format("记录计数'{0}'...{1}",dt.Rows.Count,qry.TableName));返回数据;}}}}catch(Exceptionex){System.Diagnostics.Debug.WriteLine("引发异常..."+qry.TableName);System.Diagnostics.Debug.WriteLine(ex.Message);返回新的System.Data.DataTable(qry.TableName);}}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: