2015-04-23 2 views
0

В моей таблице «Пользователь» (SQL Server) есть столбец (int, null), ActiveWorkRequestId. Я пытаюсь обновить таблицу с помощью SqlDataAdapter. Это настроено с клоном команды обновления по умолчанию, основанной на определении строго типизированного набора данных XSD (Visual Studio 2010). Таким образом, команда выглядитФорматException из SQLDataAdapter.Update, вызванный нулевым значением

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 в измененной строке имеет значение NULL (как это было в исходной строке). «dt» - это заполненный DataTable из моего DataSet.

// 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 брошено:

Не удалось преобразовать значение параметра из строки к Int32.

Внутреннее исключение:

Входная строка не была в правильном формате.

Я не могу узнать, в каком столбце он выступает, но единственным столбцом int (кроме ПК) является ActiveWorkRequestId. Таким образом, кажется, что метод Update обрабатывает значение null для параметра как пустую строку и пытается принудить его к int32, даже если столбец таблицы и параметр являются обнуляемыми.

Почему он не может просто установить столбец в нуль (тем более, что он уже равен нулю в базе данных)? Могу ли я что-нибудь сделать?

Возможно, мне стоит упомянуть, что проект был просто импортирован в VS2010 (.NET 4.0) из VS2003 (.NET 1.1), где все работало нормально. Вот почему SqlDataAdapter создается в коде, а не только с помощью TableAdapter, созданного дизайнером XSD - конструктор .NET 1.1 не создал TableAdapters. (Я не хочу, если возможно, регенерировать все XSD).

+0

Похоже, что-то может пытаться присвоить строку «NULL» или «DbNull» как значение параметра вместо экземпляра DbNull.Value. –

+0

Строка DataTable определенно содержит DbNull.Value, поэтому, если это неверно расширено для параметра запроса, то это не ошибка в ADO.NET? В этом процессе нет кода пользователя. Если это происходит для всех, кто пытается обновить значение NULL int, дату/время и т. Д. С помощью null, используя SqlDataAdapter, то почему Интернет не заполнен людьми, жалующимися на это? –

+0

Похоже, что это давняя проблема, которую Microsoft не намерена решать ... см., Например, [эта ссылка] (http://forums.asp.net/t/1227689.aspx). Я могу попробовать расширение VS, упомянутое там, так как кажется невозможным использовать SqlDataAdapter для обновления, где задействуются нулевые столбцы, отличные от строки. –

ответ

1

Вместо того чтобы использовать метод CopyCommandObject(), с помощью:

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

Таким образом, проще и менее подвержены ошибкам.

+0

Код был перенесен из .NET 1.1, который не поддерживал 'SqlCommand.Clone() ', что, по-видимому, почему это было сделано этим способом. Однако я подозреваю, что в новой Framework не все необходимые свойства копируются старым кодом. –

Смежные вопросы