[英]Error while using user-defined table type in sql --> Operand type clash: varchar is incompatible with "user defined table type"
[英]MVC 300K row data table from excel into SQL using User-defined Table Types - Operand type clash
我想通過 MVC 和用戶定義的表類型將 300K + 行從 excel(熱監控數據)導入 MsSQL DB。
我選擇使用表類型和存儲過程,因為我不想循環瀏覽數據並創建動態 SQL 來上傳 300K 記錄,因為這需要一段時間來處理(嘗試過。)。
我正在使用的過程是:
完整代碼。
Public Async Function DataImport(ByVal DataImports As HttpPostedFileBase) As Task(Of ActionResult)
If DataImports Is Nothing Then Return Json(New With {Key .Status = 0, Key .Message = "No File Selected"})
Try
Dim fileData = GetDataFromCSVFile(DataImports.InputStream)
Dim dtManualHeatData = fileData.ToArray()
Dim table As DataTable = New DataTable()
table.Columns.Add("ManualHeatDataId", GetType(String))
table.Columns.Add("DateAndTime", GetType(Date))
table.Columns.Add("Pulse", GetType(Integer))
For Each Line As Object In dtManualHeatData
Dim row As DataRow = table.NewRow()
row("ManualHeatDataId") = Line.ManualHeatDataId
row("DateAndTime") = Line.DateAndTime
row("Pulse") = Line.Pulse
table.Rows.Add(row)
Next
Dim tblManualHeatData = New SqlParameter("myManualHeatDatas", SqlDbType.Structured) With {.TypeName = "dbo.ManualHeatDatasType",
.Value = table
}
Dim SQL As String = "EXEC dbo.ImportManualHeatData @myManualHeatDatas"
Await db.Database.ExecuteSqlCommandAsync(SQL, tblManualHeatData)
Return Json(New With {Key .Status = 1, Key .Message = "File Imported Successfully "})
Catch ex As Exception
Return Json(New With {Key .Status = 0, Key .Message = ex.Message})
End Try
End Function
Private Function GetDataFromCSVFile(ByVal stream As Stream) As List(Of ManualHeatData)
Dim ManualHeatList = New List(Of ManualHeatData)()
Try
Using reader = ExcelReaderFactory.CreateReader(stream)
Dim dataset = reader.AsDataSet(New ExcelDataSetConfiguration() With {
.ConfigureDataTable = Function(__) New ExcelDataTableConfiguration() With {
.UseHeaderRow = True,
.ReadHeaderRow = Function(rowReader)
rowReader.Read()
rowReader.Read()
rowReader.Read()
rowReader.Read()
rowReader.Read()
rowReader.Read()
End Function}})
If dataset.Tables.Count > 0 Then
Dim dataTable = dataset.Tables(0)
Dim Count As Long = 0
For Each objDataRow As DataRow In dataTable.Rows
Count = +1
If objDataRow.ItemArray.All(Function(x) String.IsNullOrEmpty(x?.ToString())) Then Continue For
ManualHeatList.Add(New ManualHeatData() With {
.ManualHeatDataId = Count,
.DateAndTime = objDataRow("Date").ToString(),
.Pulse = objDataRow("Pulses (Pulses)").ToString()
})
Next
End If
End Using
Catch Ex As Exception
Throw
End Try
Return ManualHeatList
End Function
上面的整個過程直到 Await db.Database.ExecuteSqlCommandAsync 大約需要 15 秒,這對我的需求來說很好。 問題是運行 db.Database.ExecuteSqlCommandAsync 時出現以下錯誤。
操作數類型沖突:ManualHeatDatasType 與 nvarchar 不兼容
我已經能夠將 go 插入 SQL 服務器並查看 SQL 已由上述代碼傳遞給它但未使用事件記錄器。 當我查看這個 SQL 語句時,它只有 3711 行長,當我使用 SSMS 激發它時,它會正確地將行添加到所需的表中。 下面是 SQL 語句的示例,如在事件記錄器中看到但未執行。
declare @p3 dbo.ManualHeatDatasType
insert into @p3 values(N'1','2020-10-14 12:31:15',0)
insert into @p3 values(N'1','2020-10-14 12:31:25',1)
insert into @p3 values(N'1','2020-10-14 12:31:35',0)
..loads more rows!...
insert into @p3 values(N'1','2020-10-14 22:48:45',0)
insert into @p3 values(N'1','2020-10-14 22:48:55',0)
insert into @p3 values(N'1','2020-10-14 22:49:05',0)
insert into @p3 values(N'1','2020-10-14 22:49:15',0)
insert into @p3 values(N'1','2020-10-14 22:49:25',0)
insert into @p3 values(N'1','2020-10-14 22:49:35',0)
exec sp_executesql N'EXEC dbo.ImportManualHeatData @myManualHeatDatas',N'@myManualHeatDatas [dbo].[ManualHeatDatasType] READONLY',@myManualHeatDatas=@p3
如果我多次重復測試,它總是在傳遞給 SQL 的 3711 行處停止並且不運行。 所以我認為這個問題與數據表/流中 3711 或 22:49:35 之后的數據有關。
但是圍繞這一點的所有數據都是干凈的,並且與之前的數據完全相同。
如果有人對哪里出了問題有任何指示或反饋,請告訴我。 干杯,理查德。
好的,找到了解決方案!
而不是使用存儲過程,表類型並將數據表映射到我找到的類型SqlBulkCopy !!!
After creating the table in the original question above I am able to use the SqlBulkCopy as below to push the whole datatable into the SQL server and the whole process of reading and importing into SQL for 300k rows from excel takes around 5 seconds!! 腦洞大開!!
Using dbcontext As ApplicationDbContext = New ApplicationDbContext()
Dim sqlCon As SqlConnection = New SqlConnection(DbContext.Database.Connection.ConnectionString)
sqlCon.Open()
Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(sqlCon)
bulkCopy.DestinationTableName = Data_Base + ".dbo.ManualHeatDatas"
Try
bulkCopy.WriteToServer(table)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
table.Dispose()
End Try
End Using
End Using
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.