A table-valued parameter is a good choice here. For starters you'd create a custom table type in SQL Server, like so:
create type dbo.IdentifierList as table (Identifier int not null);
Here's a simple C# function to create an instance of a query parameter having this type:
SqlParameter CreateIdentifierTableParameter(string name, IEnumerable<int> identifiers)
{
// Build a DataTable whose schema matches that of our custom table type.
var identifierTable = new DataTable(name);
identifierTable.Columns.Add("Identifier", typeof(long));
foreach (var identifier in identifiers)
identifierTable.Rows.Add(identifier);
return new SqlParameter
{
ParameterName = name, // The name of the parameter in the query to be run.
TypeName = "dbo.IdentifierList", // The name of our table type.
SqlDbType = SqlDbType.Structured, // Indicates a table-valued parameter.
Value = identifierTable, // The table created above.
};
}
Then you write your query with the @RoomIds
parameter treated as if it were any other table in your database, call the function created above to build the table-valued parameter, and then add it to your SQL command just like you would any other SqlParameter
. For instance:
void GetMeetings(IEnumerable<int> roomIdentifiers)
{
// A simplified version of your query to show just the relevant part:
const string sqlText = @"
select
M.*
from
Meeting M
where
exists (select 1 from @RoomIds R where M.RoomId = R.Identifier);";
using (var sqlCon = new SqlConnection("<your connection string here>"))
{
sqlCon.Open();
using (var sqlCmd = new SqlCommand(sqlText, sqlCon))
{
sqlCmd.Parameters.Add(CreateIdentifierTableParameter("RoomIds", roomIdentifiers));
// Execute sqlCmd here in whatever way is appropriate.
}
}
}
This seems like a lot of work at first, but once you've defined the SQL type and written some code to create instances of it, it's really easy to re-use wherever you need it.