如何解决OutOfMemoryException SqlCommand VarCharMax
| 我正在尝试使用ADO.NET(4.0 SP1)将大量字符串数据插入SQLExpress R2的VARCHAR(MAX)字段中。该表只有一列,即VARCHAR(MAX)。当前,字符串的大小为77012287。这是查询:insert into dbo.t_test (c1) values (@c1);
我目前正在运行一个测试应用程序,该应用程序将构造一个新字符串,如下所示:
private static void ExecuteSqlQuery(int size) {
Console.WriteLine(\"Inserting data. Parameter size: {0}\",size);
using (SqlConnection cn = new SqlConnection(SQL_CONNECTION_STRING)) {
Console.WriteLine(\"Opening database connection.\");
cn.Open();
using (SqlCommand cm = cn.CreateCommand()) {
cm.CommandType = CommandType.Text;
cm.CommandText = SQL_INSERT;
cm.CommandTimeout = SQL_COMMAND_TIMEOUT;
cm.Parameters.Add(SQL_PARM_DATA,SqlDbType.VarChar,-1).Value = new string(\'a\',size);
cm.ExecuteNonQuery();
}
Console.WriteLine(\"Closing database connection.\");
}
}
尝试以更大的值运行此方法时,我正在接收SqlException。它从不实际访问数据库(我已经分析了SQL Express)。 SqlException是ExecuteNonQuery调用上的TimeoutException。如果在使用较大的编号运行该方法之前运行了几次,则在ExecuteNonQuery调用上将收到System.OutOfMemoryException。似乎内部解析器正在尝试使用char数组并引发错误。如何将.NET中的大字符串值插入SQL Express?谢谢。
解决方法
有关如何将大文件流式传输到BLOB列的示例,请参见通过ASP.Net MVC从SQL Server下载和上传图像,请参阅BLOB数据的流式传输部分。您可以从codeproject下载代码。
要点是,您需要分块上传并使用
UPDATE set column.WRITE
语法,因为ADO.Net客户端没有适当的流语义。
一种替代方法是使用FILESTREAM
,因为SqlFileStream
类型确实支持流传输,请参阅FILESTREAM MVC:从SQL Server下载和上传图像以获取完整示例。但是FILESTREAM存储带有其怪癖,并不是一个微不足道的决定(特别是如果您的托管服务不提供它的话……)。
,听起来您的字符串最终出现在大对象堆上并且没有被压缩。不幸的是,我不知道强制压缩或清除大对象堆(LOH)的好方法,因此,我能提供的最佳建议是使用较短的字符串。
LOH所需要的任何东西都不仅仅是80Kb。请记住,因为字符串是不可变的,所以如果您逐步建立字符串,则在创建单个大字符串的过程中,可能会将许多不同的字符串插入到LOH中。这些其他字符串将由GC收集,并将物理内存返回给操作系统,但是由于LOH未压缩(请考虑进行碎片整理),因此它们将继续用尽进程可用的地址空间,通常将其限制为仅有2GB。此时,您将开始看到OutOfMemory异常。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。