// See at the end what you need in SQL Server! using System; using System.Data; using System.Data.SqlClient; using System.Collections.Generic; using Microsoft.SqlServer.Server; class TVPdemo { // Connection string. Change to fit to your environment. private const string connstr = "Application Name=TVPdemo;Integrated Security=SSPI;" + "Data Source=.\\IKI;Initial Catalog=tempdb"; // Procedure to print messages from SQL Server, errors or informational // messages. private static void PrintSqlMsgs(SqlErrorCollection msgs) { foreach (SqlError e in msgs) { Console.WriteLine ( "Msg {0}, Severity {1}, State: {2}, Procedure {3}, Line no: {4}", e.Number.ToString(), e.Class.ToString(), e.State.ToString(), e.Procedure, e.LineNumber.ToString() ); Console.WriteLine(e.Message); } } // Handler for messages from SQL Server. For this demo, we do not // distinguish between errors and informational messages. private static void SqlInfoMessage(object sender, SqlInfoMessageEventArgs ea) { PrintSqlMsgs(ea.Errors); } // Simple generic routine to print the contents of a data set. private static void PrintDataSet(DataSet ds) { Console.WriteLine("============= Dataset ======================="); if (ds.Tables.Count == 0) { Console.WriteLine("Empty dataset"); } else { foreach (DataTable tbl in ds.Tables) { Console.WriteLine("----------------------------------------"); foreach (DataColumn col in tbl.Columns) { Console.Write(col.ColumnName + "\t"); } Console.WriteLine(); foreach (DataRow row in tbl.Rows) { foreach (DataColumn col in tbl.Columns) { Console.Write(row[col].ToString() + "\t"); } Console.WriteLine(); } } } } // This helper routine sets up our SQL Connection. private static SqlConnection setup_connection () { // Open the connection. SqlConnection cn = new SqlConnection(connstr); // Handle user errors with callbacks, rather than exception. cn.InfoMessage += SqlInfoMessage; cn.FireInfoMessageEventOnUserErrors = true; return cn; } // This procedure shows how pass a value to a TVP to a stored procedure // using a List<SqlDataRecord>. private static void list_example() { // Our sample input data. int[] products = {9, 12, 27, 37}; // Here we use a List<SqlDataRecord>. SqlDataRecord is the namespace // using Microsoft.SqlServer.Server. List <SqlDataRecord> product_list = new List<SqlDataRecord>(); // Create an SqlMetaData object that describes our table type. SqlMetaData[] tvp_definition = {new SqlMetaData("n", SqlDbType.Int)}; // Loop over the products. foreach (int prodid in products) { // Create a new record, using the metadata array above. SqlDataRecord rec = new SqlDataRecord(tvp_definition); rec.SetInt32(0, prodid); // Set the value. product_list.Add(rec); // Add it to the list. } // Open a connection. using (SqlConnection cn = setup_connection()) { // Set up an SqlCommand to call the stored procedure. using (SqlCommand cmd = cn.CreateCommand()) { // The procedure call itself. cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "dbo.get_product_names"; // Add the table parameter, for table enum value to use is // Structured. TVPs are input only. cmd.Parameters.Add("@prodids", SqlDbType.Structured); cmd.Parameters["@prodids"].Direction = ParameterDirection.Input; // We should specify the table type (although when calling a // a procedure, this is not mandatory). cmd.Parameters["@prodids"].TypeName = "integer_list_tbltype"; // Then we specify the value, this is our List<SqlDataRecord>. cmd.Parameters["@prodids"].Value = product_list; // Time to run the command. To keep the code brief we use a // DataAdapter.Fill, although this may not be the most efficient. using (SqlDataAdapter da = new SqlDataAdapter(cmd)) using (DataSet ds = new DataSet()) { da.Fill(ds); PrintDataSet(ds); } } } } // This procedure shows how to pass a TVP using a DataTable. This time // we don't use a stored procedure, but a plain SQL statement to show // that this is possible. private static void datatable_example() { // Our sample input data. string [] custids = {"ALFKI", "BONAP", "CACTU", "FRANK"}; // Create a DataTable, and define its single column. DataTable custid_list = new DataTable(); custid_list.Columns.Add("custid", typeof(String)); // Loop over the customer in the table. foreach (string custid in custids) { // Create a new row, save the customer id, and add it to the table. DataRow dr = custid_list.NewRow(); dr["custid"] = custid; custid_list.Rows.Add(dr); } // Open connection. using(SqlConnection cn = setup_connection()) { // Set up the command. using(SqlCommand cmd = cn.CreateCommand()) { // The query to run. cmd.CommandText = @"SELECT C.CustomerID, C.CompanyName FROM Northwind.dbo.Customers C WHERE C.CustomerID IN (SELECT id.custid FROM @custids id)"; cmd.CommandType = CommandType.Text; // Add the table parameter. cmd.Parameters.Add("@custids", SqlDbType.Structured); cmd.Parameters["@custids"].Direction = ParameterDirection.Input; // When we use CommandType.Text, we must specify the name of // the table type. cmd.Parameters["@custids"].TypeName = "custid_list_tbltype"; // We pass our data table as the parameter value. cmd.Parameters["@custids"].Value = custid_list; // Time to run the command. To keep the code brief we use a // DataAdapter.Fill, although this may not be the most efficient. using (SqlDataAdapter da = new SqlDataAdapter(cmd)) using (DataSet ds = new DataSet()) { da.Fill(ds); PrintDataSet(ds); } } } } // This example shows how to pass data using a DataReader. The example // is a little cheesy, as it just reads a list of values from an SQL // command. Normally, you would use a DataReader when you have your // input in some other data source: a file, an access database, or even // a TCP port. (In the latter case you would need to implement // IDataReader yourself.) private static void datareader_example() { // Set up a connection using OleDb client; we could at least // pretend that it is something else than SQL Server. System.Data.OleDb.OleDbConnection remote_conn = new System.Data.OleDb.OleDbConnection( "Provider=SQLOLEDB;" + connstr); remote_conn.Open(); // Set up the command. System.Data.OleDb.OleDbCommand remote_cmd = remote_conn.CreateCommand(); remote_cmd.CommandType = CommandType.Text; remote_cmd.CommandText = "SELECT n FROM (VALUES(9), (12), (27), (37)) as t (n)"; // Set up the reader. System.Data.OleDb.OleDbDataReader oledb_reader = remote_cmd.ExecuteReader(); // Now we have the reader, we can run the SQL Server command as // in the other two examples. using (SqlConnection cn = setup_connection()) { using (SqlCommand cmd = cn.CreateCommand()) { // The procedure call. cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "dbo.get_product_names"; // Add the table parameter. cmd.Parameters.Add("@prodids", SqlDbType.Structured); cmd.Parameters["@prodids"].Direction = ParameterDirection.Input; cmd.Parameters["@prodids"].TypeName = "integer_list_tbltype"; // Then we specify the value, and this time this is the // OleDB data reader. cmd.Parameters["@prodids"].Value = oledb_reader; // And run the command. using (SqlDataAdapter da = new SqlDataAdapter(cmd)) using (DataSet ds = new DataSet()) { da.Fill(ds); PrintDataSet(ds); } } } // Cleanup the remote reader. oledb_reader.Close(); oledb_reader.Dispose(); remote_cmd.Dispose(); remote_conn.Dispose(); } private static void Main() { // We use a plain exception handler just to make sure that errors are // printed to command-line window, without getting a message box about // unhandled exception. try { // Run the two examples. list_example(); datatable_example(); datareader_example(); } catch (Exception ex) { // For SQL errors, print the full story. (But note that only SQL // errors with severity >= 17 will end up here, since we use // FireInfoMessageEventOnUserErrors.) if (ex is SqlException) { SqlException sqlex = (SqlException) ex; PrintSqlMsgs(sqlex.Errors); } else { Console.WriteLine(ex.ToString()); } } } } /* Create this in SQL Server to be able to run the demo code. You will need the Northwind database. CREATE TYPE integer_list_tbltype AS TABLE (n int NOT NULL PRIMARY KEY) CREATE TYPE custid_list_tbltype AS TABLE(custid nchar(5) NOT NULL PRIMARY KEY) go CREATE PROCEDURE get_product_names @prodids integer_list_tbltype READONLY AS SELECT p.ProductID, p.ProductName FROM Northwind..Products p WHERE p.ProductID IN (SELECT n FROM @prodids) */
http://www.sommarskog.se/arraylist-2008/tvpdemo.cs