Да, использование таблицы многозначных параметров SQL Server. Сначала нужно создать тип:
CREATE TYPE dbo.StudentIDs(ID INT PRIMARY KEY);
Теперь ваша процедура может использовать это (обратите внимание, что я изменил свои вложенные IN
запросы к собственно присоединиться):
CREATE PROCEDURE dbo.MarkStudentsAsDeleted
@IDs dbo.StudentIDs READONLY
AS
BEGIN
SET NOCOUNT ON;
UPDATE s SET IsDeleted = 1
FROM dbo.Students AS s
INNER JOIN dbo.Class AS c
ON s.StudentId = c.StudentId
INNER JOIN dbo.ClassValueTable AS ct
ON c.PassId = ct.Id
WHERE ct.IsDeleted <> 1
AND EXISTS (SELECT 1 FROM @IDs WHERE StudentID = s.StudentID);
END
GO
и код C# будет проходить в DataTable или, тем не менее, вы собрали коллекцию activeIds, а не список, разделенный запятыми.
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Rows.Add(1);
dt.Rows.Add(2);
dt.Rows.Add(3);
dt.Rows.Add(4);
... open connection etc. ...
SqlCommand cmd = new SqlCommand("dbo.MarkStudentsAsDeleted", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvp1 = cmd.Parameters.AddWithValue("@IDs", dt);
tvp1.SqlDbType = SqlDbType.Structured;
cmd.ExecuteNonQuery();
... close, dispose, etc. ...
Если вы хотите, чтобы настаивать на переходе строку в хранимую процедуру, вы должны будете использовать разделенную функцию. Например:
CREATE FUNCTION dbo.SplitInts
(
@List VARCHAR(MAX),
@Delimiter VARCHAR(255) = ','
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT [value] = y.i.value('(./text())[1]', 'int')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
GO
Теперь хранимая процедура может быть:
CREATE PROCEDURE dbo.MarkStudentsAsDeleted
@IDs VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
UPDATE s SET IsDeleted = 1
FROM dbo.Students AS s
INNER JOIN dbo.Class AS c
ON s.StudentId = c.StudentId
INNER JOIN dbo.ClassValueTable AS ct
ON c.PassId = ct.Id
WHERE ct.IsDeleted <> 1
AND EXISTS (SELECT 1 FROM dbo.SplitInts(@IDs, ',') WHERE Item = s.StudentID);
END
GO
[табличные значения параметров] (http://msdn.microsoft.com/en-us/library/bb675163.aspx) (однако, я не знаю, знает ли C# 3 'SqlDbType.Structured') –
@TimSchmelter - activeIds - это просто строка. Не могу ли я передать его как строку? – NoviceMe
Не использовать и использовать табличные параметры. Почему это должна быть строка? Разве это не из коллекции в какой-то момент? Зачем конвертировать его в строку только для того, чтобы разбить ее на нестрочную? Если вы собираетесь это сделать, просто продолжайте использовать приложение для инъекций SQL, которое вы используете сейчас ... –