Đây có thể là cách nhanh nhất để truy vấn một số lượng lớn các hàng bằng Dapper bằng danh sách ID. Tôi hứa với bạn điều này nhanh hơn hầu hết mọi cách bạn có thể nghĩ đến (ngoại trừ có thể sử dụng TVP như được đưa ra trong một câu trả lời khác, và tôi đã thử nghiệm, nhưng tôi nghi ngờ có thể chậm hơn vì bạn vẫn phải cư trú TVP). Nó là các hành tinh nhanh hơn Dapper bằng cách sử dụng IN
cú pháp và vũ trụ nhanh hơn Entity Framework theo từng hàng. Và nó thậm chí còn nhanh hơn các danh sách VALUES
hoặc UNION ALL SELECT
vật phẩm. Nó có thể dễ dàng được mở rộng để sử dụng khóa nhiều cột, chỉ cần thêm các cột bổ sung vào DataTable
, bảng tạm thời và các điều kiện nối.
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;
}
}
Hãy lưu ý rằng bạn cần tìm hiểu một chút về Chèn hàng loạt. Có các tùy chọn về kích hoạt bắn (mặc định là không), tôn trọng các ràng buộc, khóa bảng, cho phép chèn đồng thời, v.v.