Исключения readonlyexception объекта datarow объекта DataTable столбец "х" только чтение"."
у меня есть короткий фрагмент кода, который первоначально создал SqlDataAdapter объект снова и снова.
пытаясь немного упростить мои звонки, Я заменил SqlDataAdapter С sqlcommand, который и переехал в SqlConnection вне цикла.
теперь, когда я пытаюсь редактировать строки данных, возвращенных в мой DataTable, Я исключения readonlyexception бросил, что не был брошен до.
Примечание: у меня есть пользовательская функция, которая возвращает полное имя сотрудника, основываясь на их ID. Для простоты здесь я использовал "John Doe" в моем примере кода ниже, чтобы продемонстрировать свою точку зрения.
ExampleQueryOld работает с SqlDataAdapter; ExampleQueryNew выдает исключения readonlyexception всякий раз, когда я пытаюсь написать на элемент DataRow:
- ExampleQueryOld
это работает и не имеет никаких проблем:
public static DataTable ExampleQueryOld(string targetItem, string[] sqlQueryStrings) {
DataTable bigTable = new DataTable();
for (int i = 0; i < sqlQueryStrings.Length; i++) {
string sqlText = sqlQueryStrings[i];
DataTable data = new DataTable(targetItem);
using (SqlDataAdapter da = new SqlDataAdapter(sqlText, Global.Data.Connection)) {
try {
da.Fill(data);
} catch (Exception err) {
Global.LogError(_CODEFILE, err);
}
}
int rowCount = data.Rows.Count;
if (0 < rowCount) {
int index = data.Columns.IndexOf(GSTR.Employee);
for (int j = 0; j < rowCount; j++) {
DataRow row = data.Rows[j];
row[index] = "John Doe"; // This Version Works
}
bigTable.Merge(data);
}
}
return bigTable;
}
- ExampleQueryNew
в этом примере создается исключение ReadOnlyException:
public static DataTable ExampleQueryNew(string targetItem, string[] sqlQueryStrings) {
DataTable bigTable = new DataTable();
using (SqlConnection conn = Global.Data.Connection) {
for (int i = 0; i < sqlQueryStrings.Length; i++) {
string sqlText = sqlQueryStrings[i];
using (SqlCommand cmd = new SqlCommand(sqlText, conn)) {
DataTable data = new DataTable(targetItem);
try {
if (cmd.Connection.State == ConnectionState.Closed) {
cmd.Connection.Open();
}
using (SqlDataReader reader = cmd.ExecuteReader()) {
data.Load(reader);
}
} catch (Exception err) {
Global.LogError(_CODEFILE, err);
} finally {
if ((cmd.Connection.State & ConnectionState.Open) != 0) {
cmd.Connection.Close();
}
}
int rowCount = data.Rows.Count;
if (0 < rowCount) {
int index = data.Columns.IndexOf(GSTR.Employee);
for (int j = 0; j < rowCount; j++) {
DataRow row = data.Rows[j];
try {
// ReadOnlyException thrown below: "Column 'index' is read only."
row[index] = "John Doe";
} catch (ReadOnlyException roErr) {
Console.WriteLine(roErr.Message);
}
}
bigTable.Merge(data);
}
}
}
}
return bigTable;
}
почему я могу писать DataRow элемент в одном случае, но не в других?
потому что SqlConnection все еще открыт или SqlDataAdapter делать что-то за кулисами?
3 ответов
используя DataAdapter.Fill
не загружает схему базы данных, которая включает, является ли столбец первичным ключом или нет, и доступен ли столбец только для чтения или нет. Чтобы загрузить схему базы данных, используйте DataAdapter.FillSchema
, но это не ваши вопросы.
используя DataReader
для заполнения таблицы загружает схему. Итак,index
столбец доступен только для чтения (вероятно, потому, что это первичный ключ) и эта информация загружается в DataTable
. Тем самым предотвращая изменение данных в таблица.
Я думаю, что @k3b получил это право; установив ReadOnly = false
, вы должны иметь возможность записывать в таблицу данных.
foreach (System.Data.DataColumn col in tab.Columns) col.ReadOnly = false;
Я продолжал получать одно и то же исключение при попытке разных подходов. Что, наконец, сработало для меня, это установить свойство readonly столбца в false и изменить значение выражение столбец вместо строки[index] = "новое значение";
откройте yourdataset.файл xsd набора данных. щелкните по таблице или объекту и щелкните по конкретному столбцу, свойство readonly которого необходимо изменить. его простые решения.