В моей таблице «Пользователь» (SQL Server) есть столбец (int, null), ActiveWorkRequestId. Я пытаюсь обновить таблицу с помощью SqlDataAdapter. Это настраивается с помощью клона команды Update по умолчанию на основе определения строго типизированного набора данных 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)))
В этом примере таблица «Пользователь» имеет 3 столбца: идентификатор, имя пользователя и ActiveWorkRequestId. Параметры p2, p5 и p6 имеют связанный столбец ActiveWorkRequestId.
Параметры времени выполнения для команды обновления (из измененной строки) в этом примере:
@p1 - "myusername"
@p2 - [DBNull]
@p3 - 126
@p4 - "myusername"
@p5 - [DBNull]
@p6 - [DBNull]
Я получаю все обновленные строки (возвращается только одна), затем обновляю следующим образом. ActiveWorkRequestId в измененной строке имеет значение null (фактически, как и в исходной строке). «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, создается исключение FormatException:
Не удалось преобразовать значение параметра из String в Int32.
Внутреннее исключение:
Входная строка имела неверный формат.
Я не могу узнать, против какого столбца он возражает, но единственный столбец int (кроме PK) - это ActiveWorkRequestId. Таким образом, кажется, что метод Update обрабатывает нулевое значение параметра как пустую строку и пытается привести ее к int32, даже если столбец таблицы и параметр оба допускают значение NULL.
Почему нельзя просто установить для столбца значение null (тем более, что оно уже равно null в базе данных)? Могу ли я что-нибудь с этим сделать?
Возможно, я должен упомянуть, что проект был только что импортирован в VS2010 (.NET 4.0) из VS2003 (.NET 1.1), где все работало нормально. Вот почему SqlDataAdapter создается в коде, а не просто с использованием TableAdapter, созданного разработчиком XSD — разработчик .NET 1.1 не создавал адаптеры таблиц. (Я не хочу регенерировать все XSD, если это возможно).