You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 09:06:03