我的目的是查询一个远程数据库,查询许多(最多5000个)表中的一个(但每个表都不同)字段:
SELECT FOO FROM TABLEA WHERE ...
SELECT BAR FROM TABLEB WHERE ...
到目前为止,使用的代码是:
Public Class ValuesRepository
Private connectionString As String
Private BatchOdbcConnection As IDbConnection
Public Sub New(connectionString As String)
Me.connectionString = connectionString
BatchOdbcConnection = New Odbc.OdbcConnection("DRIVER={AspenTech ODBC driver for Production Record Manager};" + connectionString)
End Sub
PublicFunction GetAllBatchValues(tagList As IEnumerable(Of BatchTag)) As IEnumerable(Of IEnumerable(Of Double?))
Dim returnList As New List(Of IEnumerable(Of Double?))
If tagList.Count = 0 Then Return returnList
BatchOdbcConnection.Open()
For Each batchTag In tagList
Dim result As Double? = GetBatchList(batchTag.fieldName, batchTag.tableName)
If result Is Nothing Then
Continue For
Else
returnList.Add(result.Value)
End If
Next
BatchOdbcConnection.Close()
Return returnList
End Function
Private Function GetBatchList(fieldName As String, tableName As String) As IEnumerable(Of Double?)
Const SQLQuery As String = "SELECT ""{0}"" FROM ""{1}"";"
Dim query = String.Format(SQLQuery,
fieldName,
tableName)
Dim queryResult = BatchOdbcConnection.Query(Of Double?)(query, commandType:=CommandType.Text)
Return queryResult
End Function
End Class
我已经分析了代码,多达70%的时间是花在Dapper的Query
方法上,这效率很低。
我一直在尝试通过使其全部异步来改善此问题,以便在完成查询之前启动下一个查询:
Public Class ValuesRepository
Private connectionString As String
Public Sub New(connectionString As String)
Me.connectionString = connectionString
End Sub
Private Function GetOdbcConnection() As IDbConnection
Return New Odbc.OdbcConnection("DRIVER={AspenTech ODBC driver for Production Record Manager};" + connectionString)
End Function
Public Function GetAllBatchValues(tagList As IEnumerable(Of BatchTag)) As IEnumerable(Of IEnumerable(Of Double))
Dim returnList As New List(Of IEnumerable(Of Double?))
If tagList.Count = 0 Then Return returnList
Dim tasks As New List(Of Task(Of IEnumerable(Of Double?)))
For Each batchTag In tagList
tasks.Add(GetBatchList(batchTag.fieldName, batchTag.tableName))
Next
Task.WaitAll(tasks.ToArray())
For Each task In tasks
Dim result = task.Result
If result Is Nothing Then
Continue For
Else
returnList.Add(result.Value)
End If
Next
Return returnList
End Function
Private Async Function GetBatchList(fieldName As String, tableName As String) As Task(Of IEnumerable(Of Double?))
Console.WriteLine("Begin " + fieldName + " -> " + tableName)
Using conn = GetOdbcConnection()
Const SQLQuery As String = "SELECT ""{0}"" FROM ""{1}"";"
Dim query = String.Format(SQLQuery,
fieldName,
tableName)
Dim queryResult = Await conn.QueryAsync(Of Double?)(query, commandType:=CommandType.Text)
Console.WriteLine("End " + fieldName + " -> " + tableName)
Return queryResult
End Using
End Function
End Class
我曾期望它会启动所有查询,然后等待结果,并因此在控制台中读取如下内容:
Begin: Foo -> TableA
Begin: Bar -> TableB
...
End: Bar -> TableB
End: Foo-> TableA
相反,控制台显示:
Begin: Foo -> TableA
End: Foo-> TableA
Begin: Bar -> TableB
从时序上很明显,应用程序实际上正在等待每次调用后查询结束。
我在做什么错了?
答案 0 :(得分:0)
尝试将Await conn.QueryAsync替换为Await Task.Delay,看看是否可行。如果它能正常工作,那么您会收到一个新问题“为什么Await conn.QueryAsync阻止所有活动任务?”。检查您的驱动程序版本是否支持异步调用。可能有一个叫做QueryAsync的方法,但是在后面,它调用了不支持Async的驱动程序。