【发布时间】:2015-03-18 19:01:41
【问题描述】:
我有两个计时器。其中一个计时器从 plc 检索数据并更新数据表中的相关数据行。在另一个计时器中,我将该数据表作为参数发送到存储过程。问题是,有时我的 sqlCommand.ExecuteNonQuery() 会给我一个 ArgumentOutOfRangeException。我的数据表中有 128 行。我从 plc 读取了 512 个字节。一行代表一个浮点值(即4字节)
我无法理解 ArgumentOutOfRange 异常。变量计数适合行数。问题是什么。为什么我有时会出现这个错误?
这是我的代码
void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timer1.Stop();
byte[] data = new byte[512];
int res = dc.readManyBytes(libnodave.daveDB, 19, 0, 512, data);
if (res == 0)
{
for (int i = 0; i < 128; i++)
{
byte[] temp = new byte[] { data[(i * 4 + 3)], data[(i * 4 + 2)], data[(i * 4 + 1)], data[(i * 4)] };
double value = Math.Truncate(Convert.ToDouble(BitConverter.ToSingle(temp, 0)) * 100) / 100;
DataRow row = dtAddress.Rows[i];
switch (row["DataType"].ToString())
{
case "REAL":
DataRow[] rValues = dtValue.Select("AddressID = " + row["ID"]);
foreach (DataRow rValue in rValues)
{
rValue["Value"] = value;
rValue["LastUpdate"] = DateTime.Now;
}
break;
}
}
}
}
void timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
using (SqlCommand crudValues = new SqlCommand("dbo.crudValues", connection))
{
crudValues.CommandType = CommandType.StoredProcedure;
SqlParameter param = crudValues.Parameters.AddWithValue("@tblValue", dtValue);
param.SqlDbType = SqlDbType.Structured;
crudValues.ExecuteNonQuery();
}
}
--SQL 存储过程
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[crudValues]
@tblValue as dbo.tblValue READONLY
AS
BEGIN
SET NOCOUNT ON;
UPDATE tblValue SET tblValue.Value = t.Value, tblValue.LastUpdate = t.LastUpdate FROM tblValue INNER JOIN @tblValue t ON tblValue.ID = t.ID
END
堆栈跟踪;
at System.Data.SqlClient.TdsParser.TdsExecuteRPC(_SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc, Boolean sync, TaskCompletionSource`1 completion, Int32 startRpc, Int32 startParam)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at GazMotoruPLCScanner.Program.timer2_Elapsed(Object sender, ElapsedEventArgs e) in d:\Projeler\TRES ENERJİ\GazMotoruPLCScanner\Program.cs:line 106
at System.Timers.Timer.MyTimerCallback(Object state)
【问题讨论】:
-
你能发布异常的消息吗?
-
@mainvoid 异常消息是
index was out of range. must be nonnegative and less than the size of the collection我也把存储过程放到了我的问题中 -
原因可能是我填充数据表的方式吗?我通过 SqlDataAdapter 填充它。我将该数据适配器包装到 sqlcommandbuilder 中。
-
你确定异常是由ExecuteNonQuery方法抛出的吗?
-
两个定时器是否有可能同时触发?可能是您正在更改
DataTable的内容,而它正被另一个计时器处理程序发送到数据库?我在您的代码中没有看到任何对这种并发的处理。
标签: c# sql timer sqlcommand