SQL Server 2008 (oder neuer)
Erstellen Sie zunächst in Ihrer Datenbank die folgenden zwei Objekte:
CREATE TYPE dbo.IDList
AS TABLE
(
ID INT
);
GO
CREATE PROCEDURE dbo.DoSomethingWithEmployees
@List AS dbo.IDList READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT ID FROM @List;
END
GO
Jetzt in Ihrem C # -Code:
// Obtain your list of ids to send, this is just an example call to a helper utility function
int[] employeeIds = GetEmployeeIds();
DataTable tvp = new DataTable();
tvp.Columns.Add(new DataColumn("ID", typeof(int)));
// populate DataTable from your List here
foreach(var id in employeeIds)
tvp.Rows.Add(id);
using (conn)
{
SqlCommand cmd = new SqlCommand("dbo.DoSomethingWithEmployees", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvparam = cmd.Parameters.AddWithValue("@List", tvp);
// these next lines are important to map the C# DataTable object to the correct SQL User Defined Type
tvparam.SqlDbType = SqlDbType.Structured;
tvparam.TypeName = "dbo.IDList";
// execute query, consume results, etc. here
}
SQL Server 2005
Wenn Sie SQL Server 2005 verwenden, würde ich weiterhin eine Split-Funktion über XML empfehlen. Erstellen Sie zunächst eine Funktion:
CREATE FUNCTION dbo.SplitInts
(
@List VARCHAR(MAX),
@Delimiter VARCHAR(255)
)
RETURNS TABLE
AS
RETURN ( SELECT Item = CONVERT(INT, Item) FROM
( SELECT Item = x.i.value('(./text())[1]', 'varchar(max)')
FROM ( SELECT [XML] = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>') + '</i>').query('.')
) AS a CROSS APPLY [XML].nodes('i') AS x(i) ) AS y
WHERE Item IS NOT NULL
);
GO
Jetzt kann Ihre gespeicherte Prozedur einfach sein:
CREATE PROCEDURE dbo.DoSomethingWithEmployees
@List VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
SELECT EmployeeID = Item FROM dbo.SplitInts(@List, ',');
END
GO
Und in Ihrem C # -Code müssen Sie nur die Liste als '1,2,3,12'
...
Ich finde, dass die Methode zum Durchlaufen von Parametern mit Tabellenwerten die Wartbarkeit einer Lösung, die sie verwendet, vereinfacht und im Vergleich zu anderen Implementierungen, einschließlich XML und Aufteilen von Zeichenfolgen, häufig eine höhere Leistung aufweist.
Die Eingaben sind klar definiert (niemand muss raten, ob das Trennzeichen ein Komma oder ein Semikolon ist), und wir haben keine Abhängigkeiten von anderen Verarbeitungsfunktionen, die nicht offensichtlich sind, ohne den Code für die gespeicherte Prozedur zu überprüfen.
Im Vergleich zu Lösungen mit benutzerdefiniertem XML-Schema anstelle von UDTs umfasst dies eine ähnliche Anzahl von Schritten, aber meiner Erfahrung nach ist das Verwalten, Verwalten und Lesen von Code weitaus einfacher.
In vielen Lösungen benötigen Sie möglicherweise nur einen oder einige dieser UDTs (benutzerdefinierte Typen), die Sie für viele gespeicherte Prozeduren wiederverwenden. Wie in diesem Beispiel besteht die allgemeine Anforderung darin, eine Liste von ID-Zeigern zu durchlaufen. Der Funktionsname beschreibt, welchen Kontext diese IDs darstellen sollen. Der Typname sollte generisch sein.