views:

114

answers:

1

I'm trying to test out the new table-valued parameter functionality of SQL 2008 by calling a stored procedure using ADO.NET, but I'm running into a problem where the parameter seems to contain no rows when it gets to the stored procedure. The UDT looks like this:

CREATE TYPE [dbo].[PersonType] AS TABLE(
[FirstName] [varchar](50) NULL,
[LastName] [varchar](50) NULL,
[Birthdate] [date] NULL)

The stored proc looks like this:

 CREATE PROCEDURE [dbo].[AddPeople]
 (@peopleToAdd dbo.PersonType READONLY)
 AS
 BEGIN
      IF (SELECT COUNT(*) FROM @peopleToAdd) > 0
      BEGIN
           SELECT 'Has rows'
      END
      ELSE
      BEGIN
           SELECT 'Does NOT have rows'
      END
 END

And finally, the .NET code is this (brace yourself, it's a lot):

public class Program
{
    static void Main(string[] args)
    {
        PersonCollection people = 
            new PersonCollection()
              {
                 new Person
                 {
                    FirstName = "John",
                    LastName = "Doe",
                    Birthdate = new DateTime(1975, 12, 1)
                 },
                 new Person
                 {
                    FirstName = "Randall",
                    LastName = "Stevens",
                    Birthdate = new DateTime(1935, 7, 10)
                 }
               };

        using(SqlConnection conn = new SqlConnection("Data Source=localhost\\sqlexpress;Initial Catalog=TVPExample;Integrated Security=SSPI;"))
        {
            conn.Open();

            SqlCommand cmd = new SqlCommand("AddPeople", conn);

            SqlParameter parameter = cmd.Parameters.AddWithValue("@peopleToAdd", people);
            parameter.SqlDbType = SqlDbType.Structured;
            parameter.TypeName = "dbo.PersonType";

            string result = cmd.ExecuteScalar().ToString();

            Console.WriteLine(result);
        }
    }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime Birthdate { get; set; }
}

public class PersonCollection : List<Person>, IEnumerable<SqlDataRecord>
{
    #region Implementation of IEnumerable<SqlDataRecord>
    IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator()
    {
        SqlDataRecord rec = new SqlDataRecord(
            new SqlMetaData("FirstName", SqlDbType.VarChar, 50), 
            new SqlMetaData("LastName", SqlDbType.VarChar, 50), 
            new SqlMetaData("Birthdate",SqlDbType.Date));

        foreach (Person person in this)
        {
            rec.SetString(0, person.FirstName);
            rec.SetString(1, person.LastName);
            rec.SetDateTime(2, person.Birthdate);
            yield return rec;
        }
    }
    #endregion
}

I used this blog post as an example. I always get "Does NOT contain rows" as a result, but looking at the Visual Studio debugger shows that the collection I'm passing in contains the two values I put in there. Any ideas? What am I missing?

+3  A: 

Add this:

cmd.CommandType = CommandType.StoredProcedure;
Remus Rusanu
Good call! You can tell it's been a while since I've done raw ADO.NET! These days I'm either using NHibernate or the Enterprise Library.
Brian Sullivan