﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Stephen Elliott's Blog</title>
    <description>Technical blog about my work on AcuWeb and Babel.</description>
    <link>http://www2.webapplicationsuk.com/community/blog/blogid/4.aspx</link>
    <language>en-GB</language>
    <managingEditor>stephen.elliott@webapplicationsuk.com</managingEditor>
    <webMaster>support@webappuk.com</webMaster>
    <pubDate>Tue, 07 Feb 2012 19:21:19 GMT</pubDate>
    <lastBuildDate>Tue, 07 Feb 2012 19:21:19 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 3.5.1.19887</generator>
    <item>
      <title>Passing Table Value parameters to Stored Procedures from C#</title>
      <description>&lt;p&gt;This will only work with SQL Server 2008 and above as it requires a new feature of SQL Server only present in 2008 and 2008 R2: Table Value Parameters.&lt;/p&gt;  &lt;p&gt;Previously when we wanted to provide SQL with a set of data, e.g. a table, we had to pass in XML and parse that within the SQL. SQL’s parsing of XML isn’t great when dealing with large quantities of data. Additionally we want the data in table form anyway, so why bother with the XML? Ideally we just want to be able to pass in a table to SQL, just like we can get tables out.&lt;/p&gt;  &lt;p&gt;In this post I’m going to go through the steps in both SQL and C# to allow you to do this. My examples use C# 3.5 and above (through use of Linq) but it could be easily converted to .NET 2.0.&lt;/p&gt;  &lt;h3&gt;Step One – Create the Data Table Type in SQL &lt;/h3&gt;  &lt;p&gt;Use SQL Server Management Studio to navigate to the correct database. First thing we need to do is define a Table Type. This is a requirement of passing Table value parameters to a Stored Procedure. In this post I’m going to use an example of passing in a set of products.&lt;/p&gt;  &lt;p&gt;To create a data table type, you can use the following syntax:&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CREATE&lt;/span&gt; TYPE [dbo].[Product] &lt;span style="color: #0000ff"&gt;AS&lt;/span&gt; &lt;span style="color: #0000ff"&gt;TABLE&lt;/span&gt;(&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;     [ID] [&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;],&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     [Name] [nvarchar](&lt;span style="color: #0000ff"&gt;max&lt;/span&gt;),&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     [BestBefore] [datetime] &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; )&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This creates a type with three columns: &lt;b&gt;ID&lt;/b&gt;, of type integer, doesn’t allow nulls, &lt;b&gt;Name&lt;/b&gt;, of type nvarchar(max), again, doesn’t allow nulls, &lt;b&gt;BestBefore&lt;/b&gt;, a date time that does allow nulls.&lt;/p&gt;

&lt;p&gt;Once the data table type is created it can be found within: Programmability -&gt; Types -&gt; User-Defined Table Types on the target database and is ready to be used in stored procedures.&lt;/p&gt;

&lt;h3&gt;Step Two – Add the parameter to the Stored Procedure&lt;/h3&gt;

&lt;p&gt;Now that the Data Table type has been created, we can add the parameter to the stored procedure. When passing table types as parameter values, they must be marked as Read-Only, this is another requirement enforced by SQL Server. The syntax below shows the head of a stored procedure that will add a list of products to the database. Once inside the body of the stored procedure, the parameter can be used like any other Temporary Table Variable.&lt;/p&gt;

&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;ALTER&lt;/span&gt; &lt;span style="color: #0000ff"&gt;PROCEDURE&lt;/span&gt; [dbo].[spProductAddList] ( &lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;             @SessionID uniqueidentifier,&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;             @ProductList &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; dbo.Product readonly )&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;AS&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;BEGIN&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;    …&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;END&lt;/span&gt;    &lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;Step Three – Create an Explicit Cast Operator&lt;/h3&gt;

&lt;p&gt;There are several different options for passing the data to SQL; we found a couple of articles on this but none provided the quality of solution we wanted:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.codeproject.com/KB/cs/CSharpAndTableValueParams.aspx"&gt;http://www.codeproject.com/KB/cs/CSharpAndTableValueParams.aspx&lt;/a&gt; - This is the original article we found; it has a good introduction to how the principles worked, but we weren’t happy with the use of an ad-hoc DataTable implementation. &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://orionseven.com/blog/tag/c/"&gt;http://orionseven.com/blog/tag/c/&lt;/a&gt; - In this article Bryan Smith uses a custom IEnumerable implementation to create his own GetEnumerator method which outputs SqlDataRecords of the correct structure/value. We preferred this method but felt we could build on it to create a nicer OO solution without the need for a separate, specific collection class. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this in mind we settled on a method that used an explicit cast operator on the class in question to create a SqlDataRecord from the base object. &lt;/p&gt;

&lt;p&gt;In the application for our example we already have a “Product” class; to this class we’re going to add the following method:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;explicit&lt;/span&gt; &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt; SqlDataRecord(Product product)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     SqlDataRecord sqlDataRecord = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SqlDataRecord(&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SqlMetaData(&lt;span style="color: #006080"&gt;"ID"&lt;/span&gt;, SqlDbType.VarChar, -1),&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SqlMetaData(&lt;span style="color: #006080"&gt;"Name"&lt;/span&gt;, SqlDbType.VarChar, -1),&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SqlMetaData(&lt;span style="color: #006080"&gt;"BestBefore"&lt;/span&gt;, SqlDbType.VarChar, -1)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         );&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;  &lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     sqlDataRecord.SetInt32(0, product.ID);&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     sqlDataRecord.SetString(1, product.Name);&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;  &lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (product.BestBefore &gt; DateTime.MinValue)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         sqlDataRecord.SetDateTime(2, product.BestBefore);&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;  &lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; sqlDataRecord;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This creates an explicit cast operator from the type product to the type SqlDataRecord. First thing we do is create the SqlDataRecord instance, in the constructor we add 3 SqlMetaData objects which define the columns of the Data Table Type we defined in step one.&lt;/p&gt;

&lt;p&gt;Once we’ve created the record, we need to set the values; this is done using the SetString/SetInt32/SetDateTime methods. When this is done we return the sqlDataRecord object which contains the data from our object in the same format as the Data Table Type in SQL.&lt;/p&gt;

&lt;h4&gt;Step Four – Passing the data from C# to SQL&lt;/h4&gt;

&lt;p&gt;Now we have a way of generating our SqlDataRecords and have told SQL what format to expect the data in, we have to program the C# to provide this to the SQL. We have to create a parameter in ADO.NET, but give it a type of “SqlDbType.Structured”. This tells SQL that it should expect a Table Variable for the value of the parameter. &lt;/p&gt;

&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (SqlCommand command = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SqlCommand(&lt;span style="color: #006080"&gt;"spProductAddList"&lt;/span&gt;, connection))&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     command.CommandType = CommandType.StoredProcedure;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;  &lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     SqlParameter productsParameter = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SqlParameter(&lt;span style="color: #006080"&gt;"@ProductList"&lt;/span&gt;, SqlDbType.Structured)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         Value =&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;                 products.Count() &gt; 0&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;                         ? products.Select(&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;                                 p =&gt; (SqlDataRecord)p)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;                         : &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     };&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;  &lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     command.Parameters.Add(productsParameter);&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;  &lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     command.ExecuteNonQuery();&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Using LINQ we cast our products into SqlDataRecord objects using the explicit cast from step 3. The result of the LINQ Select is an IEnumerable&lt;SqlDataRecord&gt; which is provided to SQL as the value. If there are no products then “Null” is provided to SQL. SQL does not seem to like a value of “default” for Table Variable parameters.&lt;/p&gt;

&lt;p&gt;And that’s it, C# passes the collection of SqlDataRecords to SQL, which can then do as it pleases with the data it has without having to resort to XML. &lt;/p&gt;

&lt;p&gt;As mentioned this will only work on SQL Server 2008 and SQL Server 2008 R2 and the example was written using C#/.NET 3.5; however it could be easily ported to .NET 2.0 by removing the use of LINQ and replacing it with a foreach loop.&lt;/p&gt;</description>
      <link>http://www.webapplicationsuk.com/community/blog/entryid/98/passing-table-value-parameters-to-stored-procedures-from-c.aspx</link>
      <author>stephen.elliott@webapplicationsuk.com</author>
      <comments>http://www.webapplicationsuk.com/community/blog/entryid/98/passing-table-value-parameters-to-stored-procedures-from-c.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.webapplicationsuk.com/community/blog/entryid/98/passing-table-value-parameters-to-stored-procedures-from-c.aspx</guid>
      <pubDate>Tue, 25 May 2010 12:34:35 GMT</pubDate>
      <slash:comments>696</slash:comments>
      <trackback:ping>http://www2.webapplicationsuk.com/DesktopModules/Blog/Trackback.aspx?id=98</trackback:ping>
    </item>
    <item>
      <title>Tr@veller Lite Interface</title>
      <description>&lt;p&gt;Recently we’ve been inserting some new functionality into Tr@veller Lite.  Alongside that we’ve also been looking at giving it a distinctively different look and feel to the existing Tr@veller product. &lt;/p&gt;&lt;a href=http://www.webapplicationsuk.com/community/blog/entryid/33/tr-veller-lite-interface.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.webapplicationsuk.com/community/blog/entryid/33/tr-veller-lite-interface.aspx</link>
      <author>stephen.elliott@webapplicationsuk.com</author>
      <comments>http://www.webapplicationsuk.com/community/blog/entryid/33/tr-veller-lite-interface.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.webapplicationsuk.com/community/blog/entryid/33/tr-veller-lite-interface.aspx</guid>
      <pubDate>Fri, 08 May 2009 16:08:35 GMT</pubDate>
      <slash:comments>26</slash:comments>
      <trackback:ping>http://www2.webapplicationsuk.com/DesktopModules/Blog/Trackback.aspx?id=33</trackback:ping>
    </item>
    <item>
      <title>AcuWeb API: Price Command</title>
      <description>&lt;p&gt;As yesterday I only covered one command, I’ll cover two today instead.  So far I’ve covered two commands, the &lt;a href="http://www2.webapplicationsuk.com/community/blog/entryid/30/acuweb-api-progress.aspx"&gt;Search&lt;/a&gt;  and &lt;a href="http://www2.webapplicationsuk.com/community/blog/entryid/31/acuweb-api-property-command.aspx"&gt;Property&lt;/a&gt; commands, today I will be focusing on the Price command. The price command a more detailed breakdown of a properties price than the Search command provides, as well as detailing its extras. These extras can include both optional and compulsory extras.&lt;/p&gt;&lt;a href=http://www.webapplicationsuk.com/community/blog/entryid/32/acuweb-api-price-command.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.webapplicationsuk.com/community/blog/entryid/32/acuweb-api-price-command.aspx</link>
      <author>stephen.elliott@webapplicationsuk.com</author>
      <comments>http://www.webapplicationsuk.com/community/blog/entryid/32/acuweb-api-price-command.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.webapplicationsuk.com/community/blog/entryid/32/acuweb-api-price-command.aspx</guid>
      <pubDate>Fri, 01 May 2009 10:30:49 GMT</pubDate>
      <slash:comments>4</slash:comments>
      <trackback:ping>http://www2.webapplicationsuk.com/DesktopModules/Blog/Trackback.aspx?id=32</trackback:ping>
    </item>
    <item>
      <title>AcuWeb API: Property Command</title>
      <description>&lt;p&gt;Another post about the AcuWeb API, since I missed posting one yesterday there will be two today. The first command I’m going to focus on today is the Property Command, more details about the request/response can be found within the &lt;a href="http://www2.webapplicationsuk.com/Portals/0/AcuWeb%20XML%20API.pdf"&gt;AcuWeb API&lt;/a&gt;, but I hope to give a general overview as to how this command can be used. For more details on AcuWeb API and the search message see my &lt;a href="http://www2.webapplicationsuk.com/community/blog/entryid/30/acuweb-api-progress.aspx"&gt;previous post&lt;/a&gt;.&lt;/p&gt;&lt;a href=http://www.webapplicationsuk.com/community/blog/entryid/31/acuweb-api-property-command.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.webapplicationsuk.com/community/blog/entryid/31/acuweb-api-property-command.aspx</link>
      <author>stephen.elliott@webapplicationsuk.com</author>
      <comments>http://www.webapplicationsuk.com/community/blog/entryid/31/acuweb-api-property-command.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.webapplicationsuk.com/community/blog/entryid/31/acuweb-api-property-command.aspx</guid>
      <pubDate>Thu, 30 Apr 2009 08:07:23 GMT</pubDate>
      <slash:comments>4</slash:comments>
      <trackback:ping>http://www2.webapplicationsuk.com/DesktopModules/Blog/Trackback.aspx?id=31</trackback:ping>
    </item>
    <item>
      <title>Acuweb API Progress</title>
      <description>&lt;p&gt;We’ve been working hard behind the scenes on AcuWeb and getting it ready to roll out as soon as we can, but a lot of the work so far has been laying the groundwork to support the degree of flexibility to websites and the booking engine that we want to provide. At this stage however, everything’s getting tied together and that initial work on backend is really paying off. This week I plan on giving a quick overview of some of the messages and how they can be accessed to give a better idea on how easy AcuWeb is to use.&lt;/p&gt;&lt;a href=http://www.webapplicationsuk.com/community/blog/entryid/30/acuweb-api-progress.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.webapplicationsuk.com/community/blog/entryid/30/acuweb-api-progress.aspx</link>
      <author>stephen.elliott@webapplicationsuk.com</author>
      <comments>http://www.webapplicationsuk.com/community/blog/entryid/30/acuweb-api-progress.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.webapplicationsuk.com/community/blog/entryid/30/acuweb-api-progress.aspx</guid>
      <pubDate>Tue, 28 Apr 2009 09:45:15 GMT</pubDate>
      <slash:comments>4</slash:comments>
      <trackback:ping>http://www2.webapplicationsuk.com/DesktopModules/Blog/Trackback.aspx?id=30</trackback:ping>
    </item>
    <item>
      <title>AcuWeb Interface</title>
      <description>&lt;p&gt;&lt;span style="font-family: courier new; font-size: 10pt"&gt;&lt;font face="verdana"&gt;From this blog I’ll be posting about the progress we make on the backend of the Acumen Website replacement project.  This system is designed to be a centralised interface that will both drive the replacement Acumen websites and also allow clients to access it directly to drive their own websites, where required.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;a href=http://www.webapplicationsuk.com/community/blog/entryid/9/acuweb-interface.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.webapplicationsuk.com/community/blog/entryid/9/acuweb-interface.aspx</link>
      <author>stephen.elliott@webapplicationsuk.com</author>
      <comments>http://www.webapplicationsuk.com/community/blog/entryid/9/acuweb-interface.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.webapplicationsuk.com/community/blog/entryid/9/acuweb-interface.aspx</guid>
      <pubDate>Thu, 19 Mar 2009 18:31:52 GMT</pubDate>
      <slash:comments>5</slash:comments>
      <trackback:ping>http://www2.webapplicationsuk.com/DesktopModules/Blog/Trackback.aspx?id=9</trackback:ping>
    </item>
  </channel>
</rss>
