我正在运行一个 .NET 4.0 应用程序,该应用程序使用 LINQ to SQL 与 SQL Server 2008 R2 标准版进行通信。我有一个表,其中有一列类型为 nvarchar(max)
,应用程序在其操作过程中使用字符串填充该列。
对于大小 > ~30 MB 的字符串,我们发现一旦插入\更新完成,字符串的一部分会被截断,并且存储在服务器中的不是完整的字符串。问题是字符串在可变位置被截断(截断后我们仍然留下超过 30 MB 的数据),所以没有一些固定点可以引导我走向某些大小限制的方向(尽管这仍然可能是这样的)。
我没有看到插入时间有任何错误,尽管有时我注意到在如此长的插入\更新过程中,SQL 服务器关闭了连接——但在这种情况下,操作不应该回滚吗?
希望能提供一些想法。不确定如何进行。
最佳答案
我怀疑它不是 SQL Server,甚至不是插入数据的连接。我想知道在设置命令参数值时甚至在应用程序中是否数据损坏。我已经尝试过连接和命令超时以在插入时引发它们,并且您假设它会回滚已取消的隐式事务是正确的。这是一个例子:
// Use connection with timeout of 1 second to generate a timeout when inserting
using (var conn = new SqlConnection(@"Data Source=(localdb)\mssqllocaldb;Integrated Security=SSPI;Initial Catalog=tempdb;Connection Timeout=1"))
using (var cmd = conn.CreateCommand())
{
cmd.CommandTimeout = 1;
conn.Open();
cmd.CommandText = @"if not exists(select * from sys.tables where name = 'LongStringTruncation')
begin
create table LongStringTruncation (Data nvarchar(max));
end";
cmd.ExecuteNonQuery();
cmd.CommandText = "insert LongStringTruncation values (@t)";
var t = cmd.CreateParameter();
t.DbType = DbType.String;
t.ParameterName = "@t";
t.Value = new String('A', 30000000); // 30,000,000 chars = 60MB
cmd.Parameters.Add(t);
cmd.ExecuteNonQuery();
}
成功时(即查询在超时前完成);以下查询显示所有 30,000,000 个字符已传输并插入;当超时失败时,表为空。
select len(Data) from LongStringTruncation;
请注意,我在这里使用的是 SQL 2014,因此 SQL 2008 R2 中可能存在错误,此测试可以发现该错误。我的测试也使用参数,如果您改为使用字符串连接来构建 SQL,这可能是另一个问题来源。
如果这些都不能解释问题,那么唯一有意义的结论是应用程序本身在插入数据之前以某种方式截断了数据。鉴于随机性,我会考虑您获取字符串数据的方式(例如,在读取结果之前没有刷新的缓冲流),或者在获取值/表示它已完成时的一些多线程竞争将是我的第一个怀疑对象。
关于c# - 插入时截断的长字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29931299/