C++/CLI访问SQL DataTable列报E1767错误有什么可行解决方案?
问题:C#逻辑迁移到C++/CLI时DataRow列访问报错E1767
我有一段运行正常的C# WinForms代码如下:
SqlConnection loginCon = new SqlConnection ("Data Source=MORTDECAI;Initial Catalog=d_Authentication;Integrated Security=True;Pooling=False;"); SqlCommand connectionCommand = new SqlCommand ("Select * From d_Info where Username=@username COLLATE Latin1_General_CS_AS and Password=@password COLLATE Latin1_General_CS_AS", loginCon); connectionCommand.Parameters.AddWithValue("@username", textUsername.Text); connectionCommand.Parameters.AddWithValue("@password", textPassword.Text); connectionCommand.Connection = loginCon; loginCon.Open(); SqlDataAdapter adaptData = new SqlDataAdapter(connectionCommand); DataSet databaseData = new DataSet(); DataTable virtualTable = new DataTable(); adaptData.Fill(databaseData, "Login"); virtualTable = databaseData.Tables["Login"]; loginCon.Close(); int count = databaseData.Tables[0].Rows.Count; if (count == 1) { if (virtualTable.Rows[0][1].ToString() == "Administrator"){ // 业务逻辑 }
请注意最后一行代码:if (virtualTable.Rows[0][1].ToString() == "Administrator")
当我将相同的逻辑迁移到C++/CLI时,上述最后一行代码无法按预期运行,对应的C++/CLI代码如下:
adaptData->Fill(dtbaseData, "AdminTable"); dtTable = dtbaseData->Tables["AdminTable"]; Database->Close(); sqlCount = dtbaseData->Tables[0]->Rows->Count; if (sqlCount == 1) { if (dtTable->Rows[0][1]->ToString() == "Administrator") { this->Hide(); res_load->Show(); }
运行时收到报错:错误代码E1767
但如果我把代码中的[1]删除,就不会触发任何错误,不过逻辑显然不符合预期。请问有什么合适的方法可以处理这个错误?
问题原因
报错的核心是C++/CLI的默认索引器语法和C#存在差异:
C#中Rows[0][1]的逻辑是先取索引为0的DataRow对象,再调用该对象的默认索引器取索引为1的列值,C#支持直接用连续方括号访问默认索引器。但C++/CLI要求显式调用默认索引器的Item属性,不能直接写[行][列]的格式。
你删掉[1]后代码不报错是因为此时你调用的是DataRow对象本身的ToString()方法,返回的是System.Data.DataRow的类型名,完全取不到对应列的数值,逻辑是错误的。
解决方法
1. 直接修正语法
将列访问的写法改为显式调用Item属性即可,修改后的判断代码如下:
if (dtTable->Rows[0]->Item[1]->ToString() == "Administrator") { // 原有业务逻辑 }
2. 推荐优化写法
用列名代替数字索引,可以避免后续表结构调整导致索引错位的问题,可维护性更高,示例如下(假设对应权限的列名为Role,可替换为你实际的列名):
if (dtTable->Rows[0]->Item["Role"]->ToString() == "Administrator") { // 原有业务逻辑 }
额外优化建议
如果需要更严谨的字符串匹配,可以使用托管字符串的Equals方法,避免引用比较的潜在问题:
if (String::Equals(dtTable->Rows[0]->Item[1]->ToString(), "Administrator")) { // 原有业务逻辑 }
内容的提问来源于stack exchange,提问作者Joey
相关产品推荐
相关产品推荐

