我的「用戶」表(SQL Server)有一個(int,null)列,ActiveWorkRequestId。 我想使用SqlDataAdapter更新表。這是基於XSD強類型數據集定義(Visual Studio 2010)的默認Update命令的克隆設置的。因此命令看起來像由空值引起的SQLDataAdapter.Update導致的FormatException
UPDATE [User] SET [Username] = @p1, [ActiveWorkRequestId] = @p2
WHERE (([Id] = @p3) AND ([Username] = @p4) AND ((@p5 = 1 AND
[ActiveWorkRequestId] IS NULL) OR ([ActiveWorkRequestId] = @p6)))
在這個例子中,表「用戶」有3列:ID,用戶名和ActiveWorkRequestId。參數p2,p5和p6都有一個關聯的ActiveWorkRequestId列。
在這個例子中的更新命令的運行時間參數(從修改的行)是:
@p1 - "myusername"
@p2 - [DBNull]
@p3 - 126
@p4 - "myusername"
@p5 - [DBNull]
@p6 - [DBNull]
我得到的所有更新的行(只有一個返回),然後更新如下。更改後的行中的ActiveWorkRequestId爲空(實際上與原始行相同)。 「dt」是從我的DataSet填充的DataTable。
// 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的更新,一個出現FormatException拋出:
未能參數值從String到的Int32轉換。
內部例外是:
輸入字符串格式不正確。
我找不到它反對哪個列,但唯一的int列(除了PK)是ActiveWorkRequestId。所以看起來,Update方法將參數的空值視爲空字符串,並試圖將其強制轉換爲int32,即使表列和參數都爲空也是如此。
爲什麼不能只將列設置爲空(特別是因爲它已經在數據庫中爲空)? 我能做些什麼嗎?
我也許應該提到該項目剛剛從VS2003(.NET 1.1)導入到VS2010(.NET 4.0),在那裏它一切正常。這就是爲什麼SqlDataAdapter是在代碼中創建的,而不是僅僅使用由XSD設計器創建的TableAdapter - .NET 1.1設計器沒有創建TableAdapter。 (如果可能的話,我不想重新生成所有的XSD)。
聽起來像某些東西可能試圖將字符串「NULL」或「DbNull」指定爲參數的值而不是DbNull.Value實例。 –
DataTable行肯定包含DbNull.Value,所以如果對於查詢參數錯誤地擴展,那麼這不會是ADO.NET中的錯誤嗎?該過程中沒有涉及用戶代碼。如果這種情況發生在每個嘗試使用SqlDataAdapter更新一個null爲空,日期/時間等爲空的人上,那麼爲什麼互聯網上沒有人抱怨呢? –
看起來這是一個長期存在的問題,微軟無意解決......請參閱[這個鏈接](http://forums.asp.net/t/1227689.aspx)。我可能會嘗試這裏提到的VS擴展,因爲它似乎不可能使用SqlDataAdapter來更新可空的非字符串列的位置。 –