Is it possible to create something like this in C# code using SqlDbCommand and SqlParameter?
DECLARE @Users TABLE (ID INT)
INSERT INTO @Users
VALUES (10),(20),(30)
SELECT COUNT(*) FROM @Users
I tried something like this:
1) DataTable creator:  
        private static DataTable CreateDataTable(IEnumerable<int> ids)
        {
        DataTable table = new DataTable();
        table.Columns.Add("ID", typeof(int));
        foreach (int id in ids)
        {
            table.Rows.Add(id);
        }
        return table;
2) Add SqlParameter:
 sqlParameters.Add(new SqlParameter()
                            {
                                ParameterName = $"@paramname",
                                SqlDbType = SqlDbType.Structured,
                                Value = table
                            });
3) Execute command (command is SELECT COUNT(*) FROM @Users), parameters is list of parameters from step 2:
using (SqlCommand cmd = new SqlCommand(command, connection))
                {
                    if (parameters != null)
                        cmd.Parameters.AddRange(parameters.ToArray());
                    SqlDataReader reader = cmd.ExecuteReader();
What I get is:
The table type parameter '@Users' must have a valid type name.
And I don't really have a real table so no type available, just want it to be:
DECLARE @Users TABLE (ID INT)
Is that doable? What I want to achieve is just pass list of values, in this case list of ints, obviously.
IN REGARD TO MARKED AS DUPLICATE:
Provided link doesn't solve the problem since it's not lack of typename problem but rather lack of typename to use. The problem is that I can't create any table and can't use any existing one to pass TypeName in SqlParameter.
ONE WORKING SOLUTION:
CREATE TYPE [dbo].[IntList] AS TABLE(
[Value] [int] NOT NULL
)
and then SqlParameter:
sqlParameters.Add(new SqlParameter()
                        {
                            ParameterName = $"@paramname",
                            SqlDbType = SqlDbType.Structured,
                            Value = table,
                            TypeName = "dbo.IntList"
                        });
Nevertheless, another step would be to use built-in type like GarethD suggested. I'm not sure if they are available in SQL Server 2016.
 
     
    