SQL服务器错误:超时已过期

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
大家好,我正在使用C#连接到SQL Server 2005。所有这些都在Windows Server 2003上运行。我必须阅读270 000 PDF文件并将其保存在文件夹中。随机时间读取和保存PDF文件时,出现此错误。我更改了超时设置,所以第四,但是我不确定还能做些什么?我可以根据要求发布代码。

谢谢

C#:
Message: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
StackTrace:    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
   at WindowsFormsApplication1.Form1.SaveUserPDF(String FolderName, String CustID) in C:\Users\Ian\Documents\Visual Studio 2008\Projects\FilesExporter\FilesExporter\Form1.cs:line 105
Source: .Net SqlClient Data Provider
TargetSite: Void OnError(System.Data.SqlClient.SqlException, Boolean)
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
我设置了执行超时,但是我现在意识到这并没有什么不同,因为当我发现它被设置为infinite时就设置了。我只是将其设置回默认值。

1.我添加了命令。CommandTimeout= 60;代码按照上面的链接,没有区别。
2.我运行了一个查询,该查询从数据库(所有PDF文件)中获取一些对象(DocBlob),然后使用文件流将其保存回HardDrive。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
嗯,我不确定这一点,也许其他人会为您提供更多信息和建议,但是,我认为值得检查该表列字段中该blob字段接受的文件大小,并确保您要上传的文件没有超出允许的空间。虽然,我确定错误 应该 如果这是问题,那就有所不同。我的想法是,如果团块空间不足, 可以不可以 暂停。但是可能值得检查。目前,我有点忙于一个项目,所以也许其他人可以分享一些其他建议以供检查。
 

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
我想您误解了我的问题,我正在从数据库中的Blob中读取内容并将PDF文件保存在硬盘驱动器上。

但是,谢谢您的建议,我希望其他人有一个好主意,我不在其中。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
哦,我真的很抱歉这次小姐 @赛伯杜克,我很累又劳累。我对那个不好!我以为您正在尝试插入数据,而不是接收数据...

在这种情况下,我建议显示用于 只要 该方法负责检索BLOB,通过查看此方法的相关源代码,我们可能会发现一些细微的差异。您能分享一下吗,我敢肯定其他人中的一个也会在有时间的时候加入进来。 :凉爽的:
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,552
地点
弗吉尼亚州切萨皮克
编程经验
10+
我运行了一个查询,该查询在数据库中获取了一些对象(DocBlob)
根据这些斑点的大小,这可能会花费很长时间。您是从数据库中查询的是基于要下载的Blob的总大小的批次吗?还是仅根据项目的固定数量下载blob?
 

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
@羊皮 我们都阿伦特吗?程序员毕竟是21世纪的劳动者。

@跳伞 您的评论使我对如何保存文件,更改方法和现在似乎运行顺利有了一个想法。如果所有工作都失败,请发布我的经验。谢谢
 

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
我几乎很高兴……它运行了一次,然后我做了一个小的代码调整,只是文件的命名有所不同(将其更改回没有任何区别)。现在错误又回来了。这是保存PDF的代码

PS。在大约+-150个PDF之后,它现在很快就破裂了


C#:
String queryString = "SELECT  dbo.DBDocument.DocumentName,dbo.DBDocBlob.Object FROM dbo.DBDocBlob, dbo.DBDocument WHERE dbo.DBDocBlob.DocumentID = dbo.DBDocument.DocumentID AND dbo.DBDocument.CustomerCode = '" + CustID + "' AND dbo.DBDocBlob.Object IS NOT NULL";

                using (SqlConnection connection = new SqlConnection(ConnectionString))
                {
                    SqlCommand command = new SqlCommand(queryString, connection);
                    connection.Open();
                    using (var myReader = command.ExecuteReader(CommandBehavior.SequentialAccess))
                    {
                    while (myReader.Read())
                    {
                        filename= myReader.GetString(0);
                        countUser++;
                        count++;

                        var filePath1 = Path.Combine(Directory.GetCurrentDirectory(), "PDFs");
                        var filePath2 = Path.Combine(filePath1, ToSafeFileName(FolderName));
                        var filePath3 = Path.Combine(filePath2, ToSafeFileName(filename) + "(" + countUser + ").pdf");

                        if (!(Directory.Exists(filePath2)))
                        {
                            DirectoryInfo di = Directory.CreateDirectory(filePath2);
                        }

                        using (var file = File.OpenWrite(filePath3))
                        {
                            const int BUFFER_SIZE = 4096;
                            var buffer = new byte[BUFFER_SIZE];
                            var index = 0;
                            int byteCount;

                            while ((byteCount = (int)myReader.GetBytes(1, index, buffer, 0, BUFFER_SIZE)) > 0)
                            {
                                file.Write(buffer, 0, byteCount);
                                index += byteCount;
                            }

                        }

                    }
                    // Close the reader and the connection.
                    myReader.Close();
                    connection.Close();
                }



                }
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
调试代码时会发生什么?

执行时查找代码中的差异。如果您在调试器中花费足够的时间,我相信您会找到它。

首先,您的代码结构不是很有效。此代码块无意进入while循环:
C#:
                        var filePath1 = Path.Combine(Directory.GetCurrentDirectory(), "PDFs");
                        var filePath2 = Path.Combine(filePath1, ToSafeFileName(FolderName));
                        var filePath3 = Path.Combine(filePath2, ToSafeFileName(filename) + "(" + countUser + ").pdf");

                        if (!(Directory.Exists(filePath2)))
                        {
                            DirectoryInfo di = Directory.CreateDirectory(filePath2);
                        }
而且我会更快地从数据库读取器传递您接收的对象,并将它们发送到新线程中,以分别执行每个接收到的文件。您的方法应该只有一项工作,并且只能做一件事。您应该对方法进行结构化处理,以完成一项工作,并针对接收到的每条数据,将每个数据发送到一个新方法中,以将文件写入单独的线程中。这段代码:
C#:
using (var file = File.OpenWrite(filePath3))
                        {
                            const int BUFFER_SIZE = 4096;
                            var buffer = new byte[BUFFER_SIZE];
                            var index = 0;
                            int byteCount;

                            while ((byteCount = (int)myReader.GetBytes(1, index, buffer, 0, BUFFER_SIZE)) > 0)
                            {
                                file.Write(buffer, 0, byteCount);
                                index += byteCount;
                            }
                        }
 

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
谢谢您的回复,是的,我知道我的代码不是很棒。 (那里没有任何借口。-它本来应该是现在应该做的超小型工具)我以相同的结果清理了它。

这就是使这个过程如此棘手的原因,我提取的PDF非常机密,因此负责人(当然不是我)禁止我将数据库中的任何数据复制到我身上。 (我们也位于世界的一半)。因此,我可以在我的PC上书写,然后必须进行远程测试,而无法正确调试或查看内容。除非我知道可以在此处应用的一些调试技术。

是的,这不是很好,并且,我已经尝试了很多次,无法更改此方案。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
还有其他需要注意的地方,虽然不太可能,但是您仍然应该检查该缓冲区,以确保接收到的文件不大于缓冲区。
const int BUFFER_SIZE = 4096;

是否可以访问实时环境并不重要。您可以并且应该为调试方案复制环境。我相信您会找到一个随机的PDF生成器,可以将其用于测试。正确的?
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,552
地点
弗吉尼亚州切萨皮克
编程经验
10+
这段代码:
C#:
const int BUFFER_SIZE = 4096;
var buffer = new byte[BUFFER_SIZE];
var index = 0;
int byteCount;

while ((byteCount = (int)myReader.GetBytes(1, index, buffer, 0, BUFFER_SIZE)) > 0)
{
    file.Write(buffer, 0, byteCount);
    index += byteCount;
}

可能很容易被以下内容代替:
C#:
myReader.GetStream(1).CopyTo(file);
 

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
This code:
C#:
const int BUFFER_SIZE = 4096;
var buffer = new byte[BUFFER_SIZE];
var index = 0;
int byteCount;

while ((byteCount = (int)myReader.GetBytes(1, index, buffer, 0, BUFFER_SIZE)) > 0)
{
    file.Write(buffer, 0, byteCount);
    index += byteCount;
}

可能很容易被以下内容代替:
C#:
myReader.GetStream(1).CopyTo(file);

不幸的是,我正在运行一个旧的.NET框架,但该框架尚未实现。可悲的是。
 

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
还有其他需要注意的地方,虽然不太可能,但是您仍然应该检查该缓冲区,以确保接收到的文件不大于缓冲区。
const int BUFFER_SIZE = 4096;

是否可以访问实时环境并不重要。您可以并且应该为调试方案复制环境。我相信您会找到一个随机的PDF生成器,可以将其用于测试。正确的?

是的,您绝对正确,我在计算机上建立了一个庞大的数据库,并且一切正常。因此,这可能与我正在执行它的机器有关。
 

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
好的,这就是我想发生的事情,在速度更快的计算机上,SQL Server可以足够快地加载记录,以便每次SQLReader想要一个新文档时都可以使用一个文档,但是在我需要处理的实际数据库上,SQL Server慢得多。如果仅执行手动查询,然后等待记录加载,这也将可见。

我在读取每一行之间增加了一个小延迟,它比以往任何时候都走得更远,所以也许就是这样。 (如果您再也没有收到我的来信,请以为是)
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,552
地点
弗吉尼亚州切萨皮克
编程经验
10+
不幸的是,我正在运行一个旧的.NET框架,但该框架尚未实现。
然后,您有更大的问题。 Microsoft于2016年1月终止了对.Net 4.0的支持。
 

赛博杜克

成员
已加入
2019年11月18日
留言内容
17
编程经验
1-3
是的,我完全知道这个问题(还有更多),幸运的是,这只是一个问题"favour"我在为某人做事,而不是我的日常工作。由于延迟,它的运行相当缓慢,但我们在那里的速度接近10%,所以我很肯定。
 

类似线程

最佳 底部