ReadOnlyException DataTable DataRow“列X是只读的”。

我有一小段代码反复创build了一个SqlDataAdapter对象。

为了简化我的调用,我用SqlCommandreplace了SqlDataAdapter ,并将SqlConnection移到了循环之外。

现在,每当我尝试编辑返回到我的DataTable的数据行时,我得到一个抛出不抛出的ReadOnlyException

注意:我有一个自定义函数,根据它的ID检索员工的全名。 为了简单起见,我在下面的示例代码中使用了“John Doe”来展示我的观点。

ExampleQueryOldSqlDataAdapter一起使用 ; 每当我尝试写入DataRow的元素时, ExampleQueryNew都会失败并返回ReadOnlyException

  • 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在幕后做了些什么?

使用DataAdapter.Fill不会加载数据库模式,其中包括列是否为主键以及列是否为只读。 要加载数据库模式,使用DataAdapter.FillSchema ,但那不是你的问题。

使用DataReader来填充表格加载模式。 所以, index列是只读的(可能是因为它是主键),并且该信息被加载到DataTable 。 从而阻止您修改表中的数据。

我认为@ k3b是对的; 通过设置ReadOnly = false ,你应该可以写入数据表。

 foreach (System.Data.DataColumn col in tab.Columns) col.ReadOnly = false; 

尝试不同的方法时,我不断得到相同的例外。 最后为我工作的是将列的ReadOnly属性设置为false,并更改Expression列的值而不是row [index] =“new value”;

打开数据集的yourdataset.xsd文件。 单击表或对象,然后单击只读属性需要更改的特定列。 简单的解决scheme。