来自 SQLDataAdapter.Update 的 FormatException 由空值引起

FormatException from SQLDataAdapter.Update caused by null value

我的 "User" table(SQL 服务器)有一个 (int,null) 列,ActiveWorkRequestId。 我正在尝试使用 SqlDataAdapter 更新 table。这是使用基于 XSD 强类型数据集定义 (Visual Studio 2010) 的默认更新命令的克隆设置的。所以命令看起来像

UPDATE [User] SET [Username] = @p1, [ActiveWorkRequestId] = @p2
 WHERE (([Id] = @p3) AND ([Username] = @p4) AND ((@p5 = 1 AND
 [ActiveWorkRequestId] IS NULL) OR ([ActiveWorkRequestId] = @p6)))

在此示例中,table "User" 有 3 列:Id、Username 和 ActiveWorkRequestId。参数 p2、p5 和 p6 都有关联的 ActiveWorkRequestId 列。

本例中更新命令(来自修改后的行)的运行时间参数是:

@p1 - "myusername"
@p2 - [DBNull]
@p3 - 126
@p4 - "myusername"
@p5 - [DBNull]
@p6 - [DBNull]

我得到所有更新的行(只有一个返回),然后更新如下。已更改行中的 ActiveWorkRequestId 为空(实际上与原始行中一样)。 "dt" 是我的数据集中填充的数据表。

// This part is inline for convenience, only done once in fact
// Some irrelevant code omitted
string query = String.Format("SELECT * FROM [{0}]", dt.TableName);
string sqlCon = ""; // connection string actually got from settings
SqlDataAdapter da = new SqlDataAdapter(query, sqlCon);
SqlCommandBuilder cb = new SqlCommandBuilder(da);
cb.QuotePrefix = "[";
cb.QuoteSuffix = "]";
da.UpdateCommand = CopyCommandObject(dt, cb.GetUpdateCommand());

// ... This part may execute more than once
DataRow[] foundRows = dt.Select("", "",
    DataViewRowState.Added | DataViewRowState.ModifiedCurrent);
da.Update(foundRows);   // Exception here

// ... defined elsewhere
private static SqlCommand CopyCommandObject(DataTable dt, SqlCommand cmd)
{
    SqlCommand r = new SqlCommand(cmd.CommandText);
    r.Connection = cmd.Connection;
    foreach (SqlParameter p in cmd.Parameters)
    {
        DataColumn dc = dt.Columns[p.SourceColumn];
        // Put this in since p.IsNullable always seems to be false
        bool nullable = dc.AllowDBNull ? true : false;
        SqlParameter newParam = new SqlParameter(
             p.ParameterName,
             p.SqlDbType,
             p.Size,
             p.Direction,
             nullable,
             p.Precision,
             p.Scale,
             p.SourceColumn,
             p.SourceVersion,
             p.Value);
        r.Parameters.Add(newParam);
    }
    return (r);
}

当我在 SqlDataAdapter 上调用 Update 时,抛出 FormatException:

无法将参数值从 String 转换为 Int32。

内部异常是:

输入的字符串格式不正确。

我无法找出它反对的列,但唯一的 int 列(除了 PK)是 ActiveWorkRequestId。因此,Update 方法似乎将参数的空值视为空字符串,并试图将其强制转换为 int32,即使 table 列和参数都可为空。

为什么不能将列设置为空(特别是因为它在数据库中已经是空的)? 我能做些什么吗?

我也许应该提到该项目刚刚从 VS2003 (.NET 1.1) 导入到 VS2010 (.NET 4.0),一切正常。这就是为什么在代码中创建 SqlDataAdapter 而不是仅使用由 XSD 设计者创建的 TableAdapter - .NET 1.1 设计者没有创建 TableAdapter。 (如果可能的话,我不想重新生成所有 XSD)。

不使用 CopyCommandObject() 方法,而是使用:

da.UpdateCommand = cb.GetUpdateCommand().Clone();

这种方式更简单,更不容易出错。