Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nullable Table Valued Parameter in Stored Procedure

I have this procedure

CREATE PROCEDURE dbo.spProcedure1
    @intArray as dbo.intArray READONLY
AS
BEGIN
-- ...
END

which use user type as a parameter

CREATE TYPE dbo.IntArray AS TABLE (IntValue int NULL)

and I am calling the procedure from the C# ASP.NET MVC 4 project

    // creating empty SQL @IntArray parameter

        var emptyIntDataTable = new DataTable();
        emptyIntDataTable.Columns.Add("IntValue");

    // calling stored procedure

        return Database.SqlQuery<int>(
            @"spProcedure1 @p1",
            new SqlParameter("p1", (object)Utils.ToDataTable(m.IntArray) ?? emptyIntDataTable)
        ).ToList();

    // ToDataTable method which is returning null

        public static DataTable ToDataTable<T>(this IList<T> data)
                {
                    if (data == null)
                        return null;

                    ... // code omitted because it is not working yet                
}

the error which is throwed when calling stored procedure is

The table type parameter 'p1' must have a valid type name.

How to pass an empty table value?

Passing the list instead of datatable throw following error

var emptyIntDataTable = new List<int>;

No mapping exists from object type System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] to a known managed provider native type.

like image 542
Muflix Avatar asked Apr 15 '26 18:04

Muflix


1 Answers

In your code:

where it says:

return Database.SqlQuery<int>(
    @"spProcedure1 @p1", new SqlParameter("p1", 
        (object)Utils.ToDataTable(m.IntArray) ?? emptyIntDataTable)
).ToList();

Change it to read:

 return m.IntArray.Length > 0? 
        Database.SqlQuery<int>(@"spProcedure1 @p1",
            new SqlParameter("p1", 
               (object)Utils.ToDataTable(m.IntArray))).ToList():
        Database.SqlQuery<int>(@"spProcedure1")).ToList();

sample to show how to not pass table parameter

CREATE TYPE dbo.KeyIds]
AS TABLE(pkId int NOT NULL,
PRIMARY KEY CLUSTERED (pkId ASC)
WITH (IGNORE_DUP_KEY = OFF))
Go
-- ------------------------------
Create procedure testProc 
    @aIds dbo.keyIds readonly
as 
Set NoCount On
    if exists (select * from @aIds) 
        Select * from @aIds
    else
        Select 'No Aids passed in'
Go
-- ------------------------------

Exec dbo.testProc -- <--- Here I am NOT passing the @aids parameter

But, even though I am NOT passing the @aids parameter it still works, and the subquery (select * from @aIds) still functions, and since it is an empty datatable the SP returns the empty message 'No Aids passed in'.

On the other hand, if you pass the parameter

Declare @MyIds dbo.keyIds
Insert @MyIds Values(1)
Insert @MyIds Values(2)
Insert @MyIds Values(3)
Insert @MyIds Values(4)
Insert @MyIds Values(5)
Exec dbo.testProc @MyIds -- <--- Here I AM passing the @aids parameter

it outputs the contents of the datatable parameter

C# code example...

 public DataTable GetAccountTransactions(IEnumerable<int> accountIds)
    {
        const string procName = "FetchAccountTransactionData";

        var acctIds = accountIds == null ? 
              new List<int>() : accountIds.ToList();
        // -------------------------------------------------
        var parms = DbParamList.Make(); 
            // DbParamList is a List<IDbDataParameter>
        // See here, ONLY ADD PARAMETER if list is NOT empty!
        if (acctIds.Count > 0) 
            parms.AddSQLTableParm("aIds", acctIds);

        try
        { // following constructs command obkect and calls SP
            return Utilities.GetDataTable(schemaNm + "." + 
                            procName, parms, copConn);
        }
        catch (SqlException dbX)
        { 
           // Exception stuff
        }
    }


    public class DbParamSortedList : SortedList<string,IDbDataParameter> { }
like image 62
Charles Bretana Avatar answered Apr 18 '26 13:04

Charles Bretana



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!