我目前正在编写一个Asp.Net站点,该站点将上传Excel文件并将内容保存到SQL Server数据库,并使用SqlBulkCopy
和DbDataReader
来执行此操作。
Excel的列和数据库表的名称完全相同。
相关代码(为清晰起见,列映射数减少)
' Connection String to Excel Workbook
Dim excelConnectionString As String = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=Excel 8.0", path)
Dim connection As New OleDbConnection()
connection.ConnectionString = excelConnectionString
Dim command As New OleDbCommand("select * from [Sheet1$]", connection)
' Bulk Copy to SQL Server
Dim bulkInsert As New SqlBulkCopy(sqlConnectionString)
bulkInsert.DestinationTableName = "UploadedOrders"
bulkInsert.BulkCopyTimeout = 0
bulkInsert.BatchSize = 50
bulkInsert.ColumnMappings.Add("Id", "Id")
bulkInsert.ColumnMappings.Add("CustomerId", "CustomerId")
bulkInsert.ColumnMappings.Add("Net", "Net")
... rest of columns
connection.Open()
Dim dr As DbDataReader = command.ExecuteReader()
bulkInsert.WriteToServer(dr)
WriteToServer
的最后一次调用引发错误
列'Net'不允许DBNull.Value。
它没有。
但是我的任何测试文件都没有Null。其中一些失败,一些有效。它抱怨不同文件的不同列,但对于特定文件总是相同。
这是我迄今为止所尝试的内容以及它的结论:
我将我的一个测试文件分成小块,试图识别数据错误。一个较小的文件工作,所以我从原始文件中添加了越来越多的行,直到它崩溃,并且确实如此。这表明数据错误。但该行看起来很好,并将其放在另一个文件中。并将它移动到倒数第二个并移除(现在)最后一行并且它可以工作。所以不是数据错误。
下一个想法是大小,当逐个添加行直到它破坏时有一个可重复的行为 - 添加行和文件将无法正常工作。删除它,它的工作原理。神奇的数字是13959行。但是一些工作的文件更大,所以我尝试了另一个不起作用的文件。它显示了完全相同的行为,但它在14259行之后破裂。所以不是尺寸问题,尽管它确实证明了尺寸相关的问题。可重复,但不同的文件不同。并且 - 再次 - 其他更大的文件工作。
尝试过SqlBulkCopy的所有类型的超时和体积增长都没有运气。
尝试使用excel 12,8的所有类型的ADODB提供程序字符串,有或没有XML,HDR等。没有变化。
尝试了三种不同的ACE驱动程序包(我运行64位Windows 10和Office 2010 64位,所以应该有一个正确,但我读它有一些问题,所以我尝试了Office 2007和也是32位)。没有变化。
添加了一个被剪切的代码,以逐行实际读取DataReader,并查找Net = Nothing的行,以防它出现读取Excel而不是写入数据库的问题。找不到任何。
在此处添加了一个问题,希望任何人都可以提供一些其他测试内容或对正在发生的事情提供一些见解。对我没有意义......
由于
更新:
尝试在Excel中添加所有列名称,按照Gordon的建议选择(谢谢!)。没用。
还尝试添加“其中xx不为空”的几个参数,这些参数在Bruce建议的不同文件中引发错误(谢谢!)。这会使错误消失并上传文件。但是,只导入文件的一部分。对于一个文件,在文件中上载了30887个记录,对于另一个文件14305上载了81195个记录。
记录数量仍然没有逻辑,Excel中仍然没有明显的数据错误或空值。这没有意义......
仍然不确定在从Excel读取或插入数据库时是否发生错误。
还在上传时在事件日志中找到了这个。不知道它是否相关。
“sql server进程内存的一个重要部分已被分页。这可能会导致性能下降。持续时间:0秒。工作集(KB):141460,已提交(KB):393412,内存利用率:35% %“。
答案 0 :(得分:0)
您是否尝试在SQL语句中指定列名?
SELECT Id, CustomerId, Net FROM [Sheet1$]
答案 1 :(得分:0)
在Excel中视觉上看起来为空的行仍然可以被Excel视为"填充"的行。如果你点击ctrl-end,通常可以看到这些。您最终会在表格中排成一排,而不是您期望的那一行。空列的工作方式相同。您通常可以通过shift选择行标题并右键单击并选择删除选项来删除这些行。
为什么不尝试使用精神错乱并将查询更改为
select * from [Sheet1$] where Net IS NOT NULL;
我认为这是使用Jet驱动程序排除空值的正确语法。
答案 2 :(得分:0)
好的,所以我发现了问题和解决方案。
原来它与BulkCopy或数据库无关。这是从Excel的读取,摇摇欲坠。
经过一些调试和临时代码后,我发现只有大约14个记录从Excel读入DataReader。
将IMEX = 1添加到连接字符串并清理了一些双+三引号,它可以正常工作。 Ace连接字符串现在是:
“Provider = Microsoft.ACE.OLEDB.12.0;数据源= {0};扩展属性=”“Excel 8.0; HDR = YES; IMEX = 1;”“”,路径)
感谢所有输入。非常感谢。