2015-04-23 25 views
0

我的「用戶」表(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)。

+0

聽起來像某些東西可能試圖將字符串「NULL」或「DbNull」指定爲參數的值而不是DbNull.Value實例。 –

+0

DataTable行肯定包含DbNull.Value,所以如果對於查詢參數錯誤地擴展,那麼這不會是ADO.NET中的錯誤嗎?該過程中沒有涉及用戶代碼。如果這種情況發生在每個嘗試使用SqlDataAdapter更新一個null爲空,日期/時間等爲空的人上,那麼爲什麼互聯網上沒有人抱怨呢? –

+0

看起來這是一個長期存在的問題,微軟無意解決......請參閱[這個鏈接](http://forums.asp.net/t/1227689.aspx)。我可能會嘗試這裏提到的VS擴展,因爲它似乎不可能使用SqlDataAdapter來更新可空的非字符串列的位置。 –

回答

1

除了使用CopyCommandObject()方法的使用:

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

這種方式更簡單,並且更不容易出錯。

+0

該代碼是從不支持'SqlCommand的.NET 1.1遷移而來的。克隆()',這大概是爲什麼它是以這種漫長的方式完成的。不過,我懷疑在新的框架中並不是所有必需的屬性都被舊代碼複製。 –

相關問題