Тут, можливо, найшвидший спосіб запиту великої кількості рядків з Dapper, використовуючи список ідентифікаторів. Я обіцяю вам, що це швидше, ніж майже будь-який інший спосіб, який ви можете придумати (за винятком можливого використання TVP, як зазначено в іншій відповіді, і який я не перевіряв, але я підозрюю, що це може бути повільніше, тому що ви все ще повинні заповнити ТВП). Це планети швидше, ніж Dapper, використовуючи IN
синтаксис і всесвітлюється швидше, ніж Entity Framework, рядок. І це навіть континенти швидше, ніж проходження у списку VALUES
або UNION ALL SELECT
предметів. Його можна легко розширити, використовуючи клавішу з декількома стовпцями, просто додайте додаткові стовпці до DataTable
, темп-таблиці та умовам об’єднання.
public IReadOnlyCollection<Item> GetItemsByItemIds(IEnumerable<int> items) {
var itemList = new HashSet(items);
if (itemList.Count == 0) { return Enumerable.Empty<Item>().ToList().AsReadOnly(); }
var itemDataTable = new DataTable();
itemDataTable.Columns.Add("ItemId", typeof(int));
itemList.ForEach(itemid => itemDataTable.Rows.Add(itemid));
using (SqlConnection conn = GetConnection()) // however you get a connection
using (var transaction = conn.BeginTransaction()) {
conn.Execute(
"CREATE TABLE #Items (ItemId int NOT NULL PRIMARY KEY CLUSTERED);",
transaction: transaction
);
new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, transaction) {
DestinationTableName = "#Items",
BulkCopyTimeout = 3600 // ridiculously large
}
.WriteToServer(itemDataTable);
var result = conn
.Query<Item>(@"
SELECT i.ItemId, i.ItemName
FROM #Items x INNER JOIN dbo.Items i ON x.ItemId = i.ItemId
DROP TABLE #Items;",
transaction: transaction,
commandTimeout: 3600
)
.ToList()
.AsReadOnly();
transaction.Rollback(); // Or commit if you like
return result;
}
}
Будьте в курсі, що вам потрібно трохи дізнатися про масові вставки. Існують варіанти щодо запуску тригерів (за замовчуванням немає), з дотриманням обмежень, блокування таблиці, дозволення одночасних вставок тощо.