Исключения 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 которого необходимо изменить. его простые решения.