为什么在C#中使用MS Access ODBC返回的是数字而不是字符串?

14
我正在使用ODBC连接在Windows 7上的Unity3D环境(Mono.net)中从一个Access文件(.mdb)获取数据,连接、断开和请求都没有错误。
但是,当我读取数据时,我只收到来自数据库的数字。它可以是整数或浮点数。但是当我尝试获取字符串时,它总是返回一个空字符串。
下面是我在我的DataBaseHandler类中用于执行请求(提取)的代码:
public ArrayList Execute(string req)
{
ArrayList output = new ArrayList();

[...]

cmd = new OdbcCommand(req);
cmd.Connection = accessConnection;

OdbcDataReader reader = cmd.ExecuteReader();
while (reader.Read()) {
    String[] row = new String[reader.FieldCount];

    for (int i=0; i<reader.FieldCount; i++) {
        if (!reader.IsDBNull(i)) { // Added if for Visual Studio
            // Getting empties strings, but work fine with numbers
            row[i] = reader.GetValue(i).ToString(); 
            // I was using GetString before, but didn't work with Visual Studio
        }
    }

    output.Add( row );
}

[...]
return output;
}

以下是我用于测试请求的内容:
ArrayList data = db.Execute("SELECT * FROM Materials");

foreach (String[] row in data) {
    string line = "";
    foreach (String s in row) {
        line += s + " - ";
    }
    Debug.Log(line); // Logging in Unity3D console
}

我收到了:
1234 - 23.1 - - -
5678 - 12.9 - - -

代替:

1234 - 23.1 - A string - Another string -
5678 - 12.9 - Hello - World -

为什么我只得到数字而没有字符串,如何进行修正?

编辑:在Visual Studio 12和Windows 7上工作正常,为了使其在Visual Studio中工作,我所做的修改并没有在Unity程序中显示出任何改进。


1
如果你在foreach循环内部放置了Debug.Log(s);,它会输出任何内容吗? - wvisaacs
2
几件事情,不要使用 ArrayList 而是使用 List<T>,其次使用调试点和逐步调试,你的第二段代码片段应该可以正常工作,问题在于你正在填充你的 ArrayList(第一段代码片段)。 - Habib
Debug.Log 在 foreach 中返回类似于“302912 - - - 32.1 - - 64 - 50”的内容。它跳过字符串。 使用 List<T> 也会得到相同的结果,但我将使用断点来查看发生了什么。 - Dean
我在问题中加了Unity3D标签,但被管理员删除了。我在标签中加入了mono.net和Unity3D环境,并在问题的介绍中提到了它们。 - Dean
1
@vsenik:我的第一个版本使用了字符串转换,但它也没有起作用。现在我正在使用MySQL导出来使我的程序工作,所以我认为这是Mono.net和Odbc之间兼容性的问题,因为它与MySQL一起正常工作。 - Dean
显示剩余21条评论
4个回答

1
我必须先说一下,我没有环境可以复制这个问题;我的答案非常基于我在Windows上使用SQL Server花费的C#,即DataReader下面使用的缓冲区会被重复使用以提高内存效率。
当数字转换为字符串时,必须为字符串分配内存,因为当前不存在任何字符串。当ToString在实际字符串上运行时,您可能会得到仍深 buried在DataReader中的字符串的引用。然后,该内存由下一条记录重用。
基本解决方案是逐个记录地进行处理,或者在循环过程中复制所需的所有内容。

0

在这里有一些糟糕的编码实践[string line = ""; string line=String.Empty;]。

在你的第二个foreach语句之前,输出所有的。你会看到问题所在。


0
我认为在从Access数据库读取数据时,您应该使用DataSet而不是DataReader!

0

在编程中,您需要使用GetString(columnOrdinal)方法,其中columnOrdinal是字符串的基于零的列。

当使用ODBC时,您需要明确返回的列的类型。因此,在您的情况下,它应该是:

public ArrayList Execute(string req)
{
ArrayList output = new ArrayList();

[...]

cmd = new OdbcCommand(req);
cmd.Connection = accessConnection;

OdbcDataReader reader = cmd.ExecuteReader();
while (reader.Read()) {
    String[] row = new String[reader.FieldCount];

    for (int i=0; i<reader.FieldCount; i++) {
        if (!reader.IsDBNull(i)) { // Added if for Visual Studio

            if (i > 0 && i < 2)
            {
                row[i] = reader.GetInt32(i);
            }
            else
            {
                row[i] = reader.GetString(i);
            }
        }
    }

    output.Add( row );
}

[...]
return output;
}

否则,我相信 GetValue 返回一个空对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接