插入时截断的长字符串

时间:2015-04-28 22:48:03

标签: c# sql-server string linq

我正在运行.NET 4.0应用程序,该应用程序使用LINQ to SQL与SQL Server 2008 R2标准版进行通信。我有一个类型为nvarchar(max)的列的表,并且应用程序使用字符串填充该列作为其操作的一部分。

对于大小不一的字符串> 〜30 MB我们发现插入\更新完成后,字符串的一部分被截断,服务器中存储的内容不是完整的字符串。问题是字符串在可变位置被截断(截断后我们仍然留下超过30 MB的数据),所以没有一些固定点可以引导我朝着某种尺寸限制的方向发展(尽管这个仍然可能是这样的。)

我没有看到插入时间有任何错误,虽然有时我注意到在这么长的插入\更新期间,SQL服务器会关闭连接 - 但是在这种情况下不应该回滚操作吗?

会欣赏一些想法。不知道如何继续。

2 个答案:

答案 0 :(得分:3)

我怀疑它不是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,这可能是问题的另一个来源。

如果这些都没有解释这个问题,那么唯一有意义的结论是应用程序本身在插入数据之前以某种方式截断数据。考虑到随机性,我会考虑你获取字符串数据的方式(例如,在读取结果之前没有刷新的缓冲流),或者在获取完成的值/信号时进行一些多线程竞争将是我的第一次嫌疑人。

答案 1 :(得分:0)

我遇到了同样的问题。 通过在存储过程中更改输入参数的数据类型来解决。

请尝试再次检查以下内容: 存储过程的输入参数的数据类型应与要插入值的表列数据类型相同。

同样在C#代码中检查相同内容。

数据类型及其长度对于Ex:VARCHAR(50),对于SP,表和代码应该相同。