代码未同步抛出 Index was out of bounds array?
Code not synced throwing Index was out of bounds array?
在您将此问题标记为重复之前,这是我不明白的棘手部分。这个错误是偶发的,我相信代码是正确的,它总是有效的,我正在处理 Reader 部分内的 if else 条件可能出现的错误。这是代码:
public static Tuple<int, string> GetIDAndString(string term)
{
try
{
using (SqlConnection con = GetConnection())
using (cmd = new SqlCommand())
using (myReader)
{
int ID = 0;
string status = string.Empty;
cmd.Connection = con;
con.Open();
cmd.CommandText = @"SELECT t.TableID, t.Status
FROM Table t WITH (NOLOCK) /* I know NOLOCK is not causing the mistake as far as I know */
WHERE t.Term = @term";
cmd.Parameters.AddWithValue("@term", term);
myReader = cmd.ExecuteReader();
while(myReader.Read())
{
ID = myReader.IsDBNull(0) ? 0 : myReader.GetInt32(0);
status = myReader.IsDBNull(1) ? string.Empty : myReader.GetString(1).Trim();
}
myReader.Close();
return new Tuple<int, string>(ID, status);
}
}
catch (Exception)
{
throw;
}
}
我知道我应该使用 class 而不是元组,但我无法更改现有代码,如您所见。所以主要问题是在生产服务器中那个方法中有一个 Index out of bounds array exception
但我无法确定问题出在哪里。
即使在查询中找不到该词,myReader 也不会输入,我会return ID = 0,status = string.Empty。有时当我调试代码并处理 develpment server
时,我的代码开始到处崩溃,向我显示测试代码的异常,我必须重新打开解决方案以避免这种情况(我还没有找到解决方案那,甚至不清洗解决方案)。
所以我希望有人在 production server
中有过类似的经验。我没有生产服务器的规格,所以我对服务器一无所知。
当您执行 ID = myReader.IsDBNull(0) ? 0 : myReader.GetInt32(0);
或 status = myReader.IsDBNull(1) ? string.Empty : myReader.GetString(1).Trim();
时可能会发生这种情况,因为结果集不符合您的预期。您应该在实际阅读 reader 行之前添加日志记录,这可能有助于您查明问题所在
我猜问题是由 myReader
字段引起的,我认为它是静态的。如果您在 https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader(v=vs.110).aspx 查看 SqlDataReader
(我想这是字段的类型)文档,您会发现实例方法不是线程安全的,因此您必须同步对该字段的访问。
using (myReader)
捕获当时 reader 的值并稍后处理。它不记得变量。这必须如此,正如您从这个示例中看到的那样:using (Random() ? myReader : null)
。显然,C# 语言不会在处理时重新执行该表达式。它只运行一次。
所以你要处理一些 old/other reader。
如果您在线程之间共享对象(可能使用静态变量),这通常是竞争条件。不要那样做。使用当地人。这里没有need/advantage使用静态变量
首先你不需要 try/catch
块,你不需要用它做任何事情。之后不要在 class 中共享 SqlDataReader
,这可能会带来问题,问题可能来自于此。您一直在覆盖 ID
和 Status
的值。可能一个好主意是在您的查询中调用 Top 1
并使用正确的字段对其进行排序。也没有必要 Dispose()
SqlCommand
,SqlCommand
的构造函数正在调用 SupressFinalization()
。
为什么会出现这个问题:假设您查询 return 的 1000 条记录,其中包含 TableID
和 Status
列,并且您正在进入 while 循环。此时,其他用户正在进入您的应用程序并执行另一种方法,该方法仅用一列覆盖 SqlDataReader
和 return 5 条记录。在 while 循环的下一次迭代中,您将收到异常。因此,对于整个 class,您永远不应将您的读者定义为 static
。静态变量在所有应用程序用户之间共享。
public static Tuple<int, string> GetIDAndString(string term)
{
int ID = 0;
string status = string.Empty;
using (SqlConnection con = GetConnection())
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = @"SELECT t.TableID, t.Status
FROM Table t WITH (NOLOCK) /* I know NOLOCK is not causing the mistake as far as I know */
WHERE t.Term = @term";
cmd.Parameters.AddWithValue("@term", term);
using(SqlDataReader myReader = cmd.ExecuteReader())
{
while(myReader.Read())
{
ID = myReader.IsDBNull(0) ? 0 : myReader.GetInt32(0);
status = myReader.IsDBNull(1) ? string.Empty : myReader.GetString(1).Trim();
}
}
}
return new Tuple<int, string>(ID, status);
}
在您将此问题标记为重复之前,这是我不明白的棘手部分。这个错误是偶发的,我相信代码是正确的,它总是有效的,我正在处理 Reader 部分内的 if else 条件可能出现的错误。这是代码:
public static Tuple<int, string> GetIDAndString(string term)
{
try
{
using (SqlConnection con = GetConnection())
using (cmd = new SqlCommand())
using (myReader)
{
int ID = 0;
string status = string.Empty;
cmd.Connection = con;
con.Open();
cmd.CommandText = @"SELECT t.TableID, t.Status
FROM Table t WITH (NOLOCK) /* I know NOLOCK is not causing the mistake as far as I know */
WHERE t.Term = @term";
cmd.Parameters.AddWithValue("@term", term);
myReader = cmd.ExecuteReader();
while(myReader.Read())
{
ID = myReader.IsDBNull(0) ? 0 : myReader.GetInt32(0);
status = myReader.IsDBNull(1) ? string.Empty : myReader.GetString(1).Trim();
}
myReader.Close();
return new Tuple<int, string>(ID, status);
}
}
catch (Exception)
{
throw;
}
}
我知道我应该使用 class 而不是元组,但我无法更改现有代码,如您所见。所以主要问题是在生产服务器中那个方法中有一个 Index out of bounds array exception
但我无法确定问题出在哪里。
即使在查询中找不到该词,myReader 也不会输入,我会return ID = 0,status = string.Empty。有时当我调试代码并处理 develpment server
时,我的代码开始到处崩溃,向我显示测试代码的异常,我必须重新打开解决方案以避免这种情况(我还没有找到解决方案那,甚至不清洗解决方案)。
所以我希望有人在 production server
中有过类似的经验。我没有生产服务器的规格,所以我对服务器一无所知。
当您执行 ID = myReader.IsDBNull(0) ? 0 : myReader.GetInt32(0);
或 status = myReader.IsDBNull(1) ? string.Empty : myReader.GetString(1).Trim();
时可能会发生这种情况,因为结果集不符合您的预期。您应该在实际阅读 reader 行之前添加日志记录,这可能有助于您查明问题所在
我猜问题是由 myReader
字段引起的,我认为它是静态的。如果您在 https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader(v=vs.110).aspx 查看 SqlDataReader
(我想这是字段的类型)文档,您会发现实例方法不是线程安全的,因此您必须同步对该字段的访问。
using (myReader)
捕获当时 reader 的值并稍后处理。它不记得变量。这必须如此,正如您从这个示例中看到的那样:using (Random() ? myReader : null)
。显然,C# 语言不会在处理时重新执行该表达式。它只运行一次。
所以你要处理一些 old/other reader。
如果您在线程之间共享对象(可能使用静态变量),这通常是竞争条件。不要那样做。使用当地人。这里没有need/advantage使用静态变量
首先你不需要 try/catch
块,你不需要用它做任何事情。之后不要在 class 中共享 SqlDataReader
,这可能会带来问题,问题可能来自于此。您一直在覆盖 ID
和 Status
的值。可能一个好主意是在您的查询中调用 Top 1
并使用正确的字段对其进行排序。也没有必要 Dispose()
SqlCommand
,SqlCommand
的构造函数正在调用 SupressFinalization()
。
为什么会出现这个问题:假设您查询 return 的 1000 条记录,其中包含 TableID
和 Status
列,并且您正在进入 while 循环。此时,其他用户正在进入您的应用程序并执行另一种方法,该方法仅用一列覆盖 SqlDataReader
和 return 5 条记录。在 while 循环的下一次迭代中,您将收到异常。因此,对于整个 class,您永远不应将您的读者定义为 static
。静态变量在所有应用程序用户之间共享。
public static Tuple<int, string> GetIDAndString(string term)
{
int ID = 0;
string status = string.Empty;
using (SqlConnection con = GetConnection())
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = @"SELECT t.TableID, t.Status
FROM Table t WITH (NOLOCK) /* I know NOLOCK is not causing the mistake as far as I know */
WHERE t.Term = @term";
cmd.Parameters.AddWithValue("@term", term);
using(SqlDataReader myReader = cmd.ExecuteReader())
{
while(myReader.Read())
{
ID = myReader.IsDBNull(0) ? 0 : myReader.GetInt32(0);
status = myReader.IsDBNull(1) ? string.Empty : myReader.GetString(1).Trim();
}
}
}
return new Tuple<int, string>(ID, status);
}