简体   繁体   中英

Database Programming in C#, returning output from Stored Proc

I am working at gaining an understanding at how to interface stored procedures with applications. My example is simple, but it doesn't display my columns and rows in the command prompt, instead it display System.Data.SqlClient.SqlDataReader. How do I display the rows from my stored procudure?

----Stored Proc--

ALTER PROCEDURE dbo.SelectID
AS
SELECT * FROM tb_User;
-----

Below is the code:

using System;
using System.Data.SqlClient;
using System.IO;


namespace ExecuteStoredProc
{
    class Program
    {
        static void Main(string[] args)
        {

            SqlConnection cnnUserMan;
            SqlCommand cmmUser;
            //SqlDataReader drdUser;

            //Instantiate and open the connection
            cnnUserMan = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=c:\\Program Files\\Microsoft SQL Server\\MSSQL10.SQLEXPRESS\\MSSQL\\DATA\\UserDB.mdf; Integrated Security=True;Connect Timeout=30;User Instance=True");
            cnnUserMan.Open();

            //Instantiate and initialize command
            cmmUser = new SqlCommand("SelectID", cnnUserMan);
            cmmUser.CommandType = System.Data.CommandType.StoredProcedure;

          //drdUser = cmmUser.ExecuteReader();
           Console.WriteLine(cmmUser.ExecuteReader());
            Console.ReadLine();
        }
    }
}

Thanks.

cmmUser. ExecuteReader() executes the stored procedure and returns a SqlDataReader object. Thus you need to use the SqlDataReader that you commented out like this:

SqlDataReader drdUser;

drdUser = cmmUser.ExecuteReader();
while(drdUser.Read()){
   //You can get at each column in the row by indexing the reader using either the column number
   // like drdUser[0] or the column name drdUser["COlumnName"]. Since I don't know the names of your
   // columns I will use numbers
   Console.WriteLine(String.Format("{0} {1} {2}", drdUser[0], drdUser[1], drdUser[2]);
}
drdUser.Close():

Also I would recommend wrapping the instantiation of your SqlConnection into a using block so that it gets disposed once you are done with it like this:

namespace ExecuteStoredProc
{
    class Program
    {
        static void Main(string[] args)
        {    
            //Instantiate and open the connection
            using(SqlConnection cnnUserMan = new SqlConnection("Your connection string")) 
            {
                cnnUserMan.Open();

                //Instantiate and initialize command
                using(SqlCommand cmmUser = new SqlCommand("SelectID", cnnUserMan))
                {
                    cmmUser.CommandType = System.Data.CommandType.StoredProcedure;

                    using(SqlDataReader drdUser = cmmUser.ExecuteReader())
                    {                     
                        while(drdUser.Read())
                        {
                            Console.WriteLine(String.Format("{0} {1} {2}", drdUser[0], drdUser[1], drdUser[2]);
                        }
                    }
                }
                Console.ReadLine();
            }
        }
    }
}

UPDATE

As per marc_s's comment, it makes sense to wrap all the disposable components, SqlConnection, SqlCommand, and SqlDataReader in a using block to make sure they are disposed of properly rather than my original solution that ONLY wrapped the SqlConnection with a using block.

UPDATE 2

As per the comment by Thorarin it looks cleaner to declare the variable as part of the using block, especially in this case where you don't need the variables outside each of the using block.

This code will show any rows returned by the stored procedure:

static void Main(string[] args)
{
    // Instantiate the connection
    using (SqlConnection cnnUserMan = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=c:\\Program Files\\Microsoft SQL Server\\MSSQL10.SQLEXPRESS\\MSSQL\\DATA\\UserDB.mdf; Integrated Security=True;Connect Timeout=30;User Instance=True"))
    using (SqlCommand cmmUser = cnnUserMan.CreateCommand())
    {
        // Initialize command
        cmmUser.CommandText = "SelectID";
        cmmUser.CommandType = CommandType.StoredProcedure;

        cnnUserMan.Open();

        using (SqlDataReader dr = cmmUser.ExecuteReader())
        {
            // Loop through returned rows
            while (dr.Read())
            {
                // Loop through all the returned columns
                // Printing column name and value
                for (int col = 0; col < dr.FieldCount; col++)
                {
                    Console.WriteLine(dr.GetName(col) + " = " + dr.GetValue(col));
                }
                Console.WriteLine();
            }
        }
    }

    Console.ReadLine();
}

There are a few changes that I've made. You may notice the use of the using statement, which ensures that the SqlConnection and the SqlDataReader objects are properly disposed. This will free up the connection to the database once you're done.

There are several ways to go about reading your information, so check the SqlDataReader documentation on MSDN . Alternatively, you might want to use the more generic IDataReader interface.

UPDATE :
Added using statement for the SqlCommand as well, which is now instantiated with CreateCommand instead. Command is now created before the connection is opened.

您不能使用Console.WriteLine来显示DataTable,因为您必须使用Foreach / for循环遍历表的每一行并逐一打印。

You will need to manually generate the output string by iterating the DataReader returned by the ExecuteReader method and building the output column by column and row by row. You could create a generic class to do this for any datareader output.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM