2017-10-16 98 views
0

只有一段代码应该运行在一组SQL Server数据上。这个想法是它读入调整一个jpeg文件并将其写回。它在单行上运行良好。但是,当运行大量数据时,随后的行由于超时而更新命令失败。不是在所有的行上,但它跳过了大多数。SqlConnection和SqlCommand超时

using System.Drawing.Imaging; 
using System.IO; 

namespace MesResizer 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var con = ConfigurationManager.ConnectionStrings["SQLconnString"].ToString(); 
      SqlConnection myConnection = new SqlConnection(con); 
      GetRows(myConnection); 
      myConnection.Close(); 
     } 

     private static void GetRows(SqlConnection connection) 
     { 
      Boolean changed = false; 

      using (connection) 
      { 
       SqlCommand command = new SqlCommand("SELECT TOP(16000) strIIImage, intIIID FROM InspectionItem;", connection); 

       try 
       { 
        Writeout("Setting up Database connection.."); 
        connection.Open(); 
       } 
       catch (Exception e) 
       { 
        Console.WriteLine(e.Message); 
        Console.ReadLine(); 
        return; 
       } 

       Writeout("DONE"); 
       SqlDataReader reader = command.ExecuteReader(); 

       if (reader.HasRows) 
       { 
        while (reader.Read()) 
        { 
         using (MemoryStream ms = new MemoryStream()) 
         { 
          int RowId = (int)reader.GetValue(reader.GetOrdinal("intIIID")); 
          Stream str; 
          changed = false; 

          try 
          { 
           str = reader.GetStream(reader.GetOrdinal("strIIImage")); 

           Image imgstr = Image.FromStream(str); 
           imgstr.Save("before.jpg", ImageFormat.Jpeg); 

           if (str.Length > 0) 
            changed = ScaleImage(Image.FromStream(str), ms); 
          } 
          catch (ArgumentException e) 
          { 
           Writeout("Stream does not have a valid image format or is Null... Unable to process image... " + RowId); 
           Writeout("Exception: " + e.Message); 
          } 

          if (changed) 
           WriteImage(ms, RowId); 
          else 
           Writeout("Image already resized: " + RowId); 
         } 
        } 
       } 
       else 
       { 
        Writeout("No rows found."); 
        Console.ReadLine(); 
       } 

       reader.Close(); 
       Console.ReadLine(); 
      } 
     } 

     private static void WriteImage(MemoryStream ms, int RowId) 
     { 
      var conf = ConfigurationManager.ConnectionStrings["SQLconnString"].ToString(); 
      SqlConnection writecon = new SqlConnection(conf); 

      writecon.Open(); 

      using (FileStream file = new FileStream("after.jpg", FileMode.Create, System.IO.FileAccess.Write)) 
      { 
       file.Write(ms.ToArray(), 0, (int)ms.Length); 
      } 

      using (SqlCommand cmd = new SqlCommand("UPDATE InspectionItem SET strIIImage = @Image WHERE intIIID = @Id", writecon)) 
      { 
       cmd.Parameters.Add("@Image", SqlDbType.VarBinary, (int)ms.Length).Value = ms.ToArray(); 
       cmd.Parameters.Add("@Id", SqlDbType.Int).Value = RowId; 
       cmd.CommandTimeout = 5; 

       try 
       { //This is where it breaks. :) 
        cmd.ExecuteNonQuery(); 
       } 
       catch (SqlException e) 
       { 
        Writeout(e.Message + "Error occured on row: " + RowId); 
        return; 
       } 
      } 

      Writeout("Succesfully Resized File: " + RowId); 
      writecon.Close(); 
     } 
    } 
} 

还有就是多余的东西会在这里,因为我一直在试图验证存储实际上是被调整大小和图像一点点其他的东西一样,是有问题的特定行。

我已经评论了发生超时的代码。 :)

任何信息或方向将不胜感激。

TIA。

编辑 在测试数据库上扫描了许多图像格式和行数超过5000+,根本没有任何问题。 我可以看到数据是一张图片的数据,因为我正在将每张图片写入磁盘,但似乎并不想一直写回数据库。非常奇怪

编辑 只要有人想知道这个决议。

最后得出结论:SQLdatareader在数据库上锁定了行。

我现在从数据库中选择数据块,将它们移动到数据表中,关闭数据记录器,并在需要时调整大小并写回。我相信关键是关闭SqlDatareader并释放任何锁。

+0

这是很多代码。请只粘贴相关部分 – Alex

+0

当然不适应更新它..不想离开任何不相关的东西。 –

回答

0

编辑:

我也是刚注意到你有cmd.CommandTimeout = 5;设置你的更新调用。这是一个相当短的超时时间,只有5秒。这个默认值是30秒,您可能很容易需要那么多时间来传输文件。

以下是初始文章:

在这里可能会发生一些事情。由于您正在使用阅读器并逐行进行,因此您将保持初始连接处于打开状态,因此最终可能会超时。

至于你的其他连接问题,如果你得到timeout while getting a connection from pool异常,而不是传统的超时,由于达到最大连接数,我不会感到惊讶。正如你在一个紧密的圈内,不断打开/关闭连接。

我也会在你的更新内部封装一个使用的连接,由于你的异常处理,连接可能不会关闭,从而导致池资源耗尽,所以在第一次超时之后你设置了失败。

这并不完美,但更改为这样可能会有所帮助。

private static void WriteImage(MemoryStream ms, int RowId) 
     { 
      var conf = ConfigurationManager.ConnectionStrings["SQLconnString"].ToString(); 
      //Added using 
      using(SqlConnection writecon = new SqlConnection(conf)) 
{ 

      writecon.Open(); 

      using (FileStream file = new FileStream("after.jpg", FileMode.Create, System.IO.FileAccess.Write)) 
      { 
       file.Write(ms.ToArray(), 0, (int)ms.Length); 
      } 

      using (SqlCommand cmd = new SqlCommand("UPDATE InspectionItem SET strIIImage = @Image WHERE intIIID = @Id", writecon)) 
      { 
       cmd.Parameters.Add("@Image", SqlDbType.VarBinary, (int)ms.Length).Value = ms.ToArray(); 
       cmd.Parameters.Add("@Id", SqlDbType.Int).Value = RowId; 
       cmd.CommandTimeout = 5; 
       try 
       { //This is where it breaks. :) 
        cmd.ExecuteNonQuery(); 
       } 
       catch (SqlException e) 
       { 
        Writeout(e.Message + "Error occured on row: " + RowId); 
        return; 
       } 
      } 
      Writeout("Succesfully Resized File: " + RowId); 
      } 
     } 
+0

当它执行查询或当我打开()时它是否从池中获得连接?执行超时已过期。操作完成之前超时的时间或服务器没有响应。 该声明已被终止。是异常消息。 :) 感谢您的帮助。 –

+0

连接在打开时建立。如果出现实际的超时时间,可能需要查看服务器上的负载,以确保不会在IO或CPU上出现问题,因为这可能会延迟,或者您正在写入的这些映像非常大。 –

+0

@ T-rent我只是再次查看你的代码并编辑我的答案。您正在设置明确的5秒超时。使用最可能太短的文件写入操作。 –

相关问题