Jeśli używasz SQL Server 2008, można utworzyć procedurę przechowywaną, która przyjmuje stole Ceniąca parametru (TVP) i użyć ADO.NET do wykonywania procedura przechowywana i przekazać DataTable do niego:
Najpierw trzeba stworzyć tego typu w serwerze SQL:
CREATE TYPE [dbo].[udt_UserId] AS TABLE(
[UserId] [int] NULL
)
Następnie trzeba napisać procedurę przechowywaną, która przyjmuje ten typ jako parametr:
CREATE PROCEDURE [dbo].[usp_DoSomethingWithTableTypedParameter]
(
@UserIdList udt_UserId READONLY
)
AS
BEGIN
SELECT userId, username
FROM Users
WHERE userId IN (SELECT UserId FROM @UserIDList)
END
Teraz z .net nie można używać LINQ, ponieważ nie obsługuje on jeszcze wartości z tabeli; więc musisz napisać funkcję, która wykonuje zwykły ADO.net, pobiera DataTable i przekazuje go do procedury przechowywanej: Napisałem ogólną funkcję, której używam, która może to zrobić dla dowolnej procedury przechowywanej, o ile bierze tylko jeden wpisany tablicą parametr, niezależnie od tego, jaki jest;
public static int ExecStoredProcWithTVP(DbConnection connection, string storedProcedureName, string tableName, string tableTypeName, DataTable dt)
{
using (SqlConnection conn = new SqlConnection(connection.ConnectionString))
{
SqlCommand cmd = new SqlCommand(storedProcedureName, conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p = cmd.Parameters.AddWithValue(tableName, dt);
p.SqlDbType = SqlDbType.Structured;
p.TypeName = tableTypeName;
conn.Open();
int rowsAffected = cmd.ExecuteNonQuery(); // or could execute reader and pass a Func<T> to perform action on the datareader;
conn.Close();
return rowsAffected;
}
}
Następnie można pisać funkcje DAL, które używają tej funkcji narzędzia z rzeczywistymi nazwami procedur składowanych; opierać się na przykład na pytanie, o to co kod wyglądałby następująco:
public int usp_DoSomethingWithTableTypedParameter(List<UserID> userIdList)
{
DataTable dt = new DataTable();
dt.Columns.Add("UserId", typeof(int));
foreach (var userId in updateList)
{
dt.Rows.Add(new object[] { userId });
}
int rowsAffected = ExecStoredProcWithTVP(Connection, "usp_DoSomethingWithTableTypedParameter", "@UserIdList", "udt_UserId", dt);
return rowsAffected;
}
Uwaga parametr „Połączenie” powyżej - I rzeczywiście korzystać z tego typu funkcji w częściowej klasy DataContext rozszerzenie LINQ DataContext z mojej funkcji TVP i nadal wykorzystuję składnię (używając var context = new MyDataContext()) tymi metodami.
To będzie działać tylko, jeśli używasz SQL Server 2008 - mam nadzieję, że jesteś, a jeśli nie, może to być świetnym powodem do aktualizacji! Oczywiście w większości przypadków i w dużych środowiskach produkcyjnych nie jest to takie proste, ale FWIW uważam, że jest to najlepszy sposób na zrobienie tego, jeśli masz dostępną technologię.
Przecinki mają być między strunami, a nie w obrębie łańcucha. –
Przecinki oddzielają każdy identyfikator użytkownika. – chobo
Jaką wersję serwera SQL? –