如何使用OracleDataReader检索给定记录的所有字段?

4

我有一个问题,类似于这个,就是如何使用OracleDataReader检索给定记录的所有字段?目前,我一直在使用以下方法,该方法每次仅返回一个列值:

public string Select_File(string filename, string subdirectory, string envID)
{
    Data_Access da = new Data_Access();
    OracleConnection conn = da.openDB();

    OracleCommand cmd = new OracleCommand();
    cmd.Connection = conn;
    cmd.CommandText = "SELECT * FROM EIP_Deployment_Files" 
        + " WHERE Filename ='" + filename + "'"
        + " AND Subdirectory = '" + subdirectory + "'"
        + " AND Environment_ID = '" + envID + "'";
    cmd.CommandType = CommandType.Text;

    string x;
    OracleDataReader dr = cmd.ExecuteReader();
    if (dr.HasRows) // file exists in DB
    {
        dr.Read();
        x = dr.GetString(2).ToString(); // return baseline filename (index 2)
    }
    else
    {
        x = "New File";
    }

    cmd.Dispose();
    da.CloseDB(conn);
    return x;
}

我确信这种方法远非完美,人们很快就会指出它的不足(实际上是由于我在ASP.NET上没有任何经验,我的主管给了我这个方法),但我真正关心的是它是否有效。我的问题是:如何修改它以返回给定记录的所有字段?
这些字段可能是VARCHAR2、CHAR或DATE数据类型(如果有区别),其中一些值可能为空。我想我可以将它们转换为字符串并作为列表返回?

注意:cmd.CommandText容易受到注入攻击的影响。 - Matt Borja
3个回答

11

如果你想要像这样的东西:

List<User> lstUser = new List<User>();
            string sqlQuery = "Select * from User_T where User_Name='" + oUser.UserName + "' And Password='" +oUser.Password + "' AND IsActive='"+1+"' AND IsDelete='"+0+"'";
            string connectionString = "Data Source=ORCL;User Id=ACCOUNTS;Password=ACCOUNTS";
            using (DBManager dbManager = new DBManager(connectionString))
            {
                try
                {

                    dbManager.Open();
                    OracleDataReader dataReader = dbManager.ExecuteDataReader(sqlQuery);
                    while (dataReader.Read())
                    {
                        oUser = new User();
                        oUser.Id = Convert.ToInt32(dataReader["ID"]);
                        oUser.CompanyId = Convert.ToInt32(dataReader["Company_ID"]);
                        oUser.BranchId = Convert.ToInt32(dataReader["Branch_ID"]);
                        oUser.UserName = Convert.ToString(dataReader["User_Name"]);
                        lstUser.Add(oUser);
                    }
                    dataReader.Close();
                    dataReader.Dispose();

                }
                catch
                (Exception)
                {


                }
                finally
                {
                    dbManager.Close();
                    dbManager.Dispose();
                }

嗯,也许吧!我得明天看看,但谢谢你的回答。 - user1985189
1
这是通过名称读取每一列,这与无论列名如何读取所有列并不完全相同。 - Jasmine
2
注意:sqlQuery容易受到注入攻击。 - Matt Borja
正如@rdev5所指出的那样,这个代码示例存在严重的安全问题,而且代码没有检查DBNull,这将导致在调用Convert.To...方法时引发异常。dbManager.Dispose方法不需要在finally块中调用,因为它已经在using块中了。 - Vamshi Krishna

6

要从DataReader的当前行中读取所有列的数据,你可以简单地使用GetValues()方法,并从数组中提取值 - 它们将是数据库类型的对象。

Object[] values;
int numColumns = dr.GetValues(values); //after "reading" a row
for (int i = 0; i < numColumns; i++) {
    //read values[i]
}

MSDN - “对于大多数应用程序来说,GetValues方法提供了一种有效的方式来检索所有列,而不是逐个检索每个列。”


抱歉我有点困惑。GetValues() 是检索每个记录字段的实际值吗? - user1985189
是的。它会填充您传入的对象数组,并将列数作为返回值返回。这是它的文档链接:http://msdn.microsoft.com/en-us/library/system.data.oracleclient.oracledatareader.getvalues.aspx - Jasmine
我不确定您想如何读取这些值,因此提供了伪代码。您可以将values[i](它将是一个对象)读入任何您想要的东西中,例如StringBuilder、数组、结构等等。 - Jasmine

4

很抱歉回答一个非常旧的问题。由于没有一个正确的答案(要么存在安全问题,要么没有检查DBNull),我决定发表自己的观点。

public async Task<StringBuilder> FetchFileDetailsAsync(string filename, string subdirectory, string envId)
    {
        var sb = new StringBuilder();
        //TODO: Check the parameters

        const string connectionString = "user id=userid;password=secret;data source=" +
                                        "(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.0.0.8)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=xe)))";

        const string selectQuery = "SELECT * FROM EIP_Deployment_Files"
                                + " WHERE Filename = :filename"
                                + " AND Subdirectory = :subdirectory"
                                + " AND Environment_ID = :envID"
                                + " AND rownum<=1";

        using (var connection = new OracleConnection(connectionString))
        using (var cmd = new OracleCommand(selectQuery, connection) {BindByName = true, FetchSize = 1 /*As we are expecting only one record*/})
        {

            cmd.Parameters.Add(":filename", OracleDbType.Varchar2).Value = filename;
            cmd.Parameters.Add(":subdirectory", OracleDbType.Varchar2).Value = subdirectory;
            cmd.Parameters.Add(":envID", OracleDbType.Varchar2).Value = envId;

            //TODO: Add Exception Handling
            await connection.OpenAsync();
            var dataReader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection);

            var rowValues = new object[dataReader.FieldCount];
            if (dataReader.Read())
            {
                dataReader.GetValues(rowValues);
                for (var keyValueCounter = 0; keyValueCounter < rowValues.Length; keyValueCounter++)
                {
                    sb.AppendFormat("{0}:{1}", dataReader.GetName(keyValueCounter), 
                        rowValues[keyValueCounter] is DBNull ? string.Empty : rowValues[keyValueCounter])
                      .AppendLine();
                }

            }
            else
            {
                //No records found, do something here
            }
            dataReader.Close();
            dataReader.Dispose();
        }
        return sb;
    }

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