超时已过期SQL Server插入

时间:2018-03-23 20:42:36

标签: c# sql sql-server sql-server-2016

我正在尝试将文件夹中的200,000个文档插入到varbinary列的SQL Server数据库中。插入80,000个文档后,我收到超时到期消息。平均文件大小约为250kb,最大文件大小为50MB。我在数据库所在的服务器上运行此c#程序。

请建议。

错误:

  

操作完成之前经过的超时时间或服务器没有响应。

代码:

string spath = @"c:\documents";
string[] files = Directory.GetFiles(spath, "*.*", SearchOption.AllDirectories);
Console.Write("Files Count:" + files.Length);

using (SqlConnection con = new SqlConnection(connectionString))
{
  con.Open();
  string insertSQL = "INSERT INTO table_Temp(doc_content, doc_path) values(@File, @path)";

  SqlCommand cmd = new SqlCommand(insertSQL, con);
  var pFile = cmd.Parameters.Add("@File", SqlDbType.VarBinary, -1);
  var pPath = cmd.Parameters.Add("@path", SqlDbType.Text);

  var tran = con.BeginTransaction();
  var fn = 0;

  foreach (string docPath in files)
  {
    string newPath = docPath.Remove(0, spath.Length);

    string archive = new DirectoryInfo(docPath).Parent.Name;
    fn += 1;

    using (var stream = new FileStream(docPath, FileMode.Open, FileAccess.Read))
    {
      pFile.Value = stream;
      pPath.Value = newPath;

      cmd.Transaction = tran;
      cmd.ExecuteNonQuery();

      if (fn % 10 == 0)
      {
        tran.Commit();
        tran = con.BeginTransaction();
        Console.Write("|");
      }

      Console.Write(".");
    }
  }

  tran.Commit();
}

3 个答案:

答案 0 :(得分:0)

为此,我建议使用SQLBulkCopy方法,因为它应该能够更轻松地处理数据插入。此外,正如其他人指出的那样,您可能希望增加命令的超时条件。

答案 1 :(得分:0)

虽然我同意这可能最适合某种批量副本,如果你必须在c#程序中这样做,你唯一的选择可能是增加超时值。您可以在通过SqlCommand创建cmd.CommandTimeout = <new timeout>;对象后执行此操作。属性CommandTimeout是一个整数,表示超时的秒数,如果您不希望它超时,则为零。 / p>

有关详细信息,请参阅MSDN docs

答案 2 :(得分:0)

您应该能够在应用程序代码中直接在该对象上设置事务的超时,这样您就不会更改sql server设置。

其次,您也可以在应用程序中构建批次。你说你可以在超时之前获得80k文档,将批量大小设置为50k,处理它们,提交它们,抓住下一批。让您的应用程序管理批处理还允许您捕获sql错误,例如超时,然后动态调整批处理大小并重试,而不会崩溃。这是首先编写应用程序的全部原因,否则您可以在管理工作室中使用向导并手动插入文件。

我强烈建议您使用其他选项进行批处理。

@Shubham Pandey还提供了一个很好的链接到SQL批量复制信息,它也有更多信息的链接。你绝对应该尝试批量复制类,看看你是否可以获得额外的收益。