坚持使用SqlDataReader.GetValues方法

时间:2014-02-06 19:19:22

标签: c# asp.net sql datareader

我正在调用SQL存储过程,该存储过程返回一个用户及其老板的小表。我想要做的是将此信息与我的应用程序的不同部分中的变量进行比较,以启用/取消编辑GridView行。为了实现这一点,似乎GetValues方法将返回我需要的东西,即存储过程返回的整个数据集。我的想法是,一旦我在我的应用程序中拥有该数据,我就可以将该数据集加载到一个数组中,然后遍历它以完成我需要做的事情。

问题是这个。在我的下面的代码中,我收到了错误

  

无法将类型'int'隐式转换为'object'

当我查看此方法的documentation时,返回值为int

我的问题是,由于存储过程包含字符串数据(用户名和老板名),为什么GetValues mehtod返回int?我的实际数据如何表示为数字?如何将数据转换为基于字符串的数组?

我一直在寻找互联网上的许多例子和信息,这似乎是新人们常见的问题。我只是不理解或得到它,我没有取得任何进展。非常感谢任何帮助!

    public Object[] GetDeptAppData()
    {
        Object[] myObject;
        string sp_deptapp, sp_status, sp_supervisor;

        //execute stored procedure to get data from database
        SqlConnection sqlConnection = new SqlConnection("Data Source=MyServer;Initial Catalog=MyCatalog;Persist Security Info=True;User ID=MyUser;Password=MyPassword");
        SqlCommand cmd = new SqlCommand();
        SqlDataReader reader;

        cmd.CommandText = "SP_Admin_DeptApp_Load";
        cmd.CommandType = CommandType.StoredProcedure;

        cmd.Connection = sqlConnection;
        sqlConnection.Open();
        reader = cmd.ExecuteReader();

        if (reader.HasRows == true)
        {
            //sp_deptapp = reader.GetValue(0).ToString();
            //sp_status = reader.GetValue(1).ToString();
            //sp_supervisor = reader.GetValue(2).ToString();

            myObject = reader.GetValues(myObject);
        }
        else
        {
            //nothing in reader, throw exception
        }
        sqlConnection.Close();

        return myObject;
    }

3 个答案:

答案 0 :(得分:10)

您遇到的错误位于以下行:

myObject = reader.GetValues(myObject);

myObject是一个对象数组,GetValues方法返回一个整数,其中包含放置在数组中的计数。因此,为了解决您的错误,您可以将该行更改为以下内容:

var count = reader.GetValues(myObject);

此外,在您的代码中,您只检索一行数据。这当然是好的,如果你只想要一排。当期望多行时,通常会循环遍历这样的行:

while (reader.Read())
{
    // Read row and add row to list
}

有关如何使用SqlDataReader的示例,请参阅此link


<强>示例

如果要检索多行并存储数据,我建议添加一个类来存储行的数据(您可能希望验证数据类型以使它们与SP返回的类型相匹配):< / p>

public class Data
{
    public string DeptApp { get; set; }
    public string Status { get; set; } // this might be another data type
    public string Supervisor { get; set; }
}

然后按如下方式检索行:

public Data[] GetDeptAppData()
{
    //execute stored procedure to get data from database
    using (SqlConnection sqlConnection = new SqlConnection("Data Source=MyServer;Initial Catalog=MyCatalog;Persist Security Info=True;User ID=MyUser;Password=MyPassword"))
    {
        SqlCommand cmd = new SqlCommand();
        cmd.CommandText = "SP_Admin_DeptApp_Load";
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Connection = sqlConnection;
        sqlConnection.Open();
        using (var reader = cmd.ExecuteReader())
        {
            if (!reader.HasRows)
            {
                // throw exception
            }
            var lst = new List<Data>();
            while (reader.Read())
            {
                var row = new Data();
                row.DeptApp = reader.GetString(0);
                row.Status = reader.GetString(1);
                row.Supervisor = reader.GetString(2);
                lst.Add(row);
            }
            return lst.ToArray();
        }
    }
}

答案 1 :(得分:3)

GetValues会返回int “数组中Object的实例数。”,因此您无法将其分配给myObject。这很神秘。它实际上意味着(我相信)为当前行返回的列值的数量。

你需要:

int numColumnsRetrieved = reader.GetValues(myObject);

或类似的东西。

您的数据随后出现在myObject内,但仅适用于当前行,根据文档“使用当前行的列值填充对象数组”。所以,你仍然需要迭代,例如:

var myObjectList = new List<object[]>(); // ... shudder ...
while (reader.Read())
{
    var myObject[] = new object[reader.FieldCount];
    int instances = reader.GetValues(myObject);
    myObjectList.Add(myObject);
}

您可能会发现使用更具体的方法很有用,例如GetString

var usersAndBosses = new List<Tuple<string, string>>();
while (reader.Read())
{
    string username = reader.GetString(0); // column index 0
    string bossname = reader.GetString(1); // column index 1
    usersAndBosses.Add(Tuple.Create(username, bossname));
}

修改

如果你希望虚假使用GetValues的返回值,你可以将一个字符串表拼成一个字符串列表:

var myStringList = new List<string>();
while (reader.Read())
{
    var myObject[] = new object[100];
    int colCount = reader.GetValues(myObject);
    for (int i = 0; i < colCount; i++)
    {
        myStringList.Add((string)myObject[i]);
    }
}

答案 2 :(得分:0)

下面有ExecuteSelectQuery(...)函数来获取所有SELECT查询的结果。

ExecuteSelectQuery的结果是一个System.Object元素数组的列表,可以在调用代码中将其转换为所需的类型。

public sealed class DbPerformer
{
    private const string mySqlServerName = "localhost";
    private const string dataBaseName = "testdb";
    private const string uid = "login";
    private const string password = "password";

    private MySqlConnection connection;

    public DbPerformer()
    {
        string connectionString;
        connectionString = "server=" + mySqlServerName + ";";
        connectionString += "Username=" + uid + ";";
        connectionString += "Password=" + password;

        connection = new MySqlConnection(connectionString);
    }

    private bool OpenConnection()
    {
        try
        {
            connection.Open();
            return true;
        }
        catch (MySqlException ex)
        {
            switch (ex.Number)
            {
                case 0:
                    Debug.WriteLine("Cannot connect to server {0}", mySqlServerName);
                    break;

                case 1045:
                    Debug.WriteLine("Invalid username/password.");
                    break;
            }
            return false;
        }
    }

    private bool CloseConnection()
    {
        try
        {
            connection.Close();
            return true;
        }
        catch (MySqlException ex)
        {
            Debug.WriteLine(ex.Message);
            return true;
        }
    }

    public List<object[]> ExecuteSelectQuery(string selectQuery)
    {
        List<object[]> resultList = new List<object[]>();

        if (true == this.OpenConnection())
        {
            MySqlCommand command = new MySqlCommand(selectQuery, connection);
            MySqlDataReader resultReader = command.ExecuteReader();

            while (resultReader.Read())
            {
                object[] resultRow = new object[resultReader.FieldCount];
                resultReader.GetValues(resultRow);
                resultList.Add(resultRow);
            }

            resultReader.Close();
            this.CloseConnection();
        }
        else
        {
            throw new Exception("Can not open connection to database.");
        }
        return resultList;
    }
}