Click here to Skip to main content
11,429,154 members (66,523 online)
Click here to Skip to main content

Table Valued Parameter in SqlServer 2008

, 16 Nov 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
How to create common procedure to insert the data in any table.

Introduction

Table Values Parameter (TVP) is one of the most useful features of SqlServer. We can create a user defined TVP and can use this as parameter in any procedure. When we worked on the large projects we need to create number of procedures to insert the data means one procedure for each table some time more than one. Here I am trying to create a single procedure to insert the data in any table with n number of columns.

Background 

Have a look on collections to use and understand this article.
 

Using the code 

To use this we need to follow the following steps.
 

1- We need to create a table to insert the data.

/* Create table Emp */
   create table Emp(
        EmpCode int,
	EmpName varchar(20)
)
Go

 2- Use following script to create a user defined Table Valued Parameter.

/* Create the User defined Table type */
CREATE TYPE [dbo].[pTableData] AS TABLE(
      [ColName] [varchar](50) NULL,
      [ColValue] [varchar](100) NULL
)

GO
 

After execution the above script a new user defined object should be displayed in Programmability>Types>User-Defined Table Type as in the following screen.

 

 3- Now we are creating a common procedure to insert the data using the User-Defined Table Types which we have created in the second point.

/* Create procedure to insert data in any table with n number of columns */
Create procedure LB_SP_InsertData
(
      @pTableName varchar(100),  --Table Name
      @pData pTableData readonly --Table data
)
as
      Declare @SqlText as varchar(5000)

      SET @SqlText='insert into '+@pTableName+'('
      select @SqlText += ColName+',' from @pData
      
      SET @SqlText=SUBSTRING(@SqlText,0,LEN(@SqlText))
      SET @SqlText+=')values(' 
      select @SqlText +=''''+ColValue+''''+',' from @pData
      
      SET @SqlText=SUBSTRING(@SqlText,0,LEN(@SqlText))
      SET @SqlText+=')'
      
      PRINT (@SqlText)
      Exec(@SqlText)
 

4- To test the procedure at back end we need to use the following script- 

/*To test the procedure at back end use following script*/
declare @par as pTableData
insert into @par values('EmpCode','50')
insert into @par values('EmpName','Rahul Pratap Singh')

--select * from @par
Exec LB_SP_InsertData 'Emp', @par
 

Ok we have done with database, its time to understand how to call this procedure from dotnet client application, we need to complete the following steps to call this procedure-

1- First of all we need to design a web page with two text box and a button as in the following screen-

 

2 - the code file of the above web page should contains the following code -

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using LoopBreak;
using System.Data;

public partial class UserRegistration : System.Web.UI.Page
{  
    Emp objUser = new Emp();
    
    protected void Page_Load(object sender, EventArgs e)
    {
       
    }

   
    protected void btnSubmit_Click(object sender, EventArgs e)
    {        
        objUser.EmpCode  = Convert.ToInt32(txtEmpCode.Text);
        objUser.EmpName = txtEmpName.Text;

        objUser.RegisterUser();
        Response.Redirect("Success.aspx");
    }
   
}
   

 

2- In business logic file, i am creating a class name Emp which contains all the properties and business logic regarding the Emp class. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;
using System.Collections;

/// <summary>
/// Summary description for CategoryMaster
/// </summary>
/// 
/// 
namespace LoopBreak
{
    public class Emp
    {
        //Object declaration section
        DataCollection objUserDataCollection = new DataCollection();
        DataDetail objDataDetails = new DataDetail();

        #region "Property Declaration"

        public int EmpCode { get; set; }
        public string EmpName { get; set; }
        
        #endregion

        public void RegisterUser()
        {
            objDataDetails._DataCollection = this.objUserDataCollection;
            objDataDetails._strTableName = clsConstant.cnsttblUser_Master;

            objDataDetails.AddDataToDataCollection("EmpCode", this.EmpCode.ToString());
            objDataDetails.AddDataToDataCollection("EmpName", this.EmpName);

            DBInsert.InsertData(objDataDetails);
            
        }
    }
}

We are creating the object of DataCollection class which is the collection of user data just like as DataTable in Ado.Net, we can also use DataTable here for the same task to store all the rows to insert. We have implemented the List and IEnumerable type in the DataCollection class to adding extra functionality to iterate the data from the class.

    /// <summary>
    /// DataCollection class stores the data to insert.
    /// </summary>
    public class DataCollection : List<DataRow>, IEnumerable<SqlDataRecord>
    {
        IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator()
        {
            var sdr = new SqlDataRecord(
                 new SqlMetaData("ColName", SqlDbType.VarChar, 50),
                 new SqlMetaData("ColValue", SqlDbType.VarChar, 5000)
             );

            foreach (DataRow objUserData in this)
            {
                sdr.SetString(0, objUserData.StrColName);
                sdr.SetString(1, objUserData.StrColValue);
                yield return sdr;
            }
        }

       
    } 

 The DataDetail class used to store the information about inserted data.Table name data collection and a method to add the data in data collection. 

 

    /// <summary>
    /// DataDetails class contains the inserted data details. 
    /// </summary>
    
    public class DataDetail
    {
        string strTableName;

        public string _strTableName
        {
            get { return strTableName; }
            set { strTableName = value; }
        }

        private DataCollection DataCollection; 

        public DataCollection _DataCollection
        {
            get { return DataCollection; }
            set { DataCollection = value; }
        }

        public void AddDataToDataCollection(string strColName, string strColValue)
        {
            DataRow objDataRow = new DataRow();
            objDataRow.StrColName = strColName;
            objDataRow.StrColValue = strColValue;
            DataCollection.Add(objDataRow);
        }
    }

 The Data Access Layer contains the following code to insert the data using the procedure-

 

    using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using Microsoft.SqlServer.Server;
/// <summary>
/// Summary description for DAL
/// </summary>
/// 
namespace LoopBreak
{
    public class DAL
    {
        public DAL() { }

        /// <summary>
        /// Returns the type of data provider that the application is using. The application will read from it's config file in the Provider element
        /// of the AppSettings node.
        /// </summary>
        /// <returns></returns>
        public static string GetProviders()
        {
            string provider = ConfigurationSettings.AppSettings["conStr"];
            return provider;
        }

    }

    #region "Procedure to insert the data"
    public class DBInsert
    {
        public static void InsertData(DataDetail pUserDetails)
        {
            SqlConnection objSqlConnection = null;
            SqlCommand objSQLComman=null;
            try
            {
                objSQLComman = new SqlCommand(clsConstant.cnstLB_SP_InsertData);
                objSQLComman.CommandType = CommandType.StoredProcedure;
                objSqlConnection = new SqlConnection(DAL.GetProviders());
                objSQLComman.Connection = objSqlConnection;    
                SqlParameter parTableName = new SqlParameter("@pTableName", SqlDbType.VarChar, 100);
                parTableName.Value = pUserDetails._strTableName;
                objSQLComman.Parameters.Add(parTableName);

                SqlParameter parData = new SqlParameter("@pData", SqlDbType.Structured);
                parData.TypeName = "dbo.pTableData";
                parData.Value = pUserDetails._DataCollection;
                objSQLComman.Parameters.Add(parData);               

                objSqlConnection.Open();
                objSQLComman.ExecuteNonQuery();
               
            }
            catch (Exception Ex)
            {
                throw Ex;
            }
            finally
            {
                if (objSQLComman != null)
                {
                    objSQLComman.Dispose();
                }
                if (objSqlConnection .State == ConnectionState.Open)
                {
                    objSqlConnection.Close();
                }
                objSqlConnection.Close();
            }

        }
    }

    /// <summary>
    /// DataDetails class contains the inserted data details. 
    /// </summary>
    
    public class DataDetail
    {
        string strTableName;

        public string _strTableName
        {
            get { return strTableName; }
            set { strTableName = value; }
        }

        private DataCollection DataCollection; 

        public DataCollection _DataCollection
        {
            get { return DataCollection; }
            set { DataCollection = value; }
        }

        public void AddDataToDataCollection(string strColName, string strColValue)
        {
            DataRow objDataRow = new DataRow();
            objDataRow.StrColName = strColName;
            objDataRow.StrColValue = strColValue;
            DataCollection.Add(objDataRow);
        }
    }

    /// <summary>
    /// DataRow class used to add a new row in DataCollection class.
    /// </summary>
    public class DataRow
    {
        string strColName;

        public string StrColName
        {
            get { return strColName; }
            set { strColName = value; }
        }
        string strColValue;

        public string StrColValue
        {
            get { return strColValue; }
            set { strColValue = value; }
        }
    }

    /// <summary>
    /// DataCollection class stores the data to insert.
    /// </summary>
    public class DataCollection : List<DataRow>, IEnumerable<SqlDataRecord>
    {
        IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator()
        {
            var sdr = new SqlDataRecord(
                 new SqlMetaData("ColName", SqlDbType.VarChar, 50),
                 new SqlMetaData("ColValue", SqlDbType.VarChar, 5000)
             );

            foreach (DataRow objUserData in this)
            {
                sdr.SetString(0, objUserData.StrColName);
                sdr.SetString(1, objUserData.StrColValue);
                yield return sdr;
            }
        }

       
    }

    #endregion
}

 We are using the InsertData methos of DBInsert class to insert the data in any table. this will insert the data in any table of n numer of columns.

 

Hope this will help to reduce the code and will give the more flexiblity to modify the code.

Thanks.

Rahul

Points of Interest  

Did you learn anything interesting/fun/annoying while writing the code? Did you do anything particularly clever or wild or zany?  

History 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rahul Pratap Singh
Software Developer HCL Technologies Ltd.
India India
No Biography provided

Comments and Discussions

 
QuestionBad performance Pin
adiprabowo25-Oct-13 8:30
memberadiprabowo25-Oct-13 8:30 
Questiongood article bad way to do it Pin
tmjunk20-Nov-11 0:29
membertmjunk20-Nov-11 0:29 
GeneralMy vote of 2 Pin
Mycroft Holmes16-Nov-11 15:04
memberMycroft Holmes16-Nov-11 15:04 
QuestionCan i chose a Emp Code? Pin
Selvin16-Nov-11 9:57
memberSelvin16-Nov-11 9:57 
QuestionFew notes Pin
Mika Wendelius16-Nov-11 9:41
memberMika Wendelius16-Nov-11 9:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150428.2 | Last Updated 16 Nov 2011
Article Copyright 2011 by Rahul Pratap Singh
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid