Năm năm trễ đến bữa tiệc.
Nó được đề cập trong các liên kết được cung cấp của câu trả lời được chấp nhận, nhưng tôi nghĩ rằng nó xứng đáng có câu trả lời rõ ràng về SO - tự động xây dựng truy vấn dựa trên các tham số được cung cấp. Ví dụ:
Thiết lập
-- drop table Person
create table Person
(
PersonId INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_Person PRIMARY KEY,
FirstName NVARCHAR(64) NOT NULL,
LastName NVARCHAR(64) NOT NULL,
Title NVARCHAR(64) NULL
)
GO
INSERT INTO Person (FirstName, LastName, Title)
VALUES ('Dick', 'Ormsby', 'Mr'), ('Serena', 'Kroeger', 'Ms'),
('Marina', 'Losoya', 'Mrs'), ('Shakita', 'Grate', 'Ms'),
('Bethann', 'Zellner', 'Ms'), ('Dexter', 'Shaw', 'Mr'),
('Zona', 'Halligan', 'Ms'), ('Fiona', 'Cassity', 'Ms'),
('Sherron', 'Janowski', 'Ms'), ('Melinda', 'Cormier', 'Ms')
GO
Thủ tục
ALTER PROCEDURE spDoSearch
@FirstName varchar(64) = null,
@LastName varchar(64) = null,
@Title varchar(64) = null,
@TopCount INT = 100
AS
BEGIN
DECLARE @SQL NVARCHAR(4000) = '
SELECT TOP ' + CAST(@TopCount AS VARCHAR) + ' *
FROM Person
WHERE 1 = 1'
PRINT @SQL
IF (@FirstName IS NOT NULL) SET @SQL = @SQL + ' AND FirstName = @FirstName'
IF (@LastName IS NOT NULL) SET @SQL = @SQL + ' AND FirstName = @LastName'
IF (@Title IS NOT NULL) SET @SQL = @SQL + ' AND Title = @Title'
EXEC sp_executesql @SQL, N'@TopCount INT, @FirstName varchar(25), @LastName varchar(25), @Title varchar(64)',
@TopCount, @FirstName, @LastName, @Title
END
GO
Sử dụng
exec spDoSearch @TopCount = 3
exec spDoSearch @FirstName = 'Dick'
Ưu điểm:
- dễ viết và dễ hiểu
- tính linh hoạt - dễ dàng tạo truy vấn cho các bộ lọc phức tạp hơn (ví dụ TOP động)
Nhược điểm:
- vấn đề hiệu suất có thể phụ thuộc vào các tham số, chỉ mục và khối lượng dữ liệu được cung cấp
Không trả lời trực tiếp, nhưng liên quan đến vấn đề aka bức tranh lớn
Thông thường, các quy trình lọc được lưu trữ này không trôi nổi xung quanh, nhưng được gọi từ một số lớp dịch vụ. Điều này để lại tùy chọn di chuyển logic nghiệp vụ (lọc) từ lớp SQL sang lớp dịch vụ.
Một ví dụ là sử dụng LINQ2SQL để tạo truy vấn dựa trên các bộ lọc được cung cấp:
public IList<SomeServiceModel> GetServiceModels(CustomFilter filters)
{
var query = DataAccess.SomeRepository.AllNoTracking;
// partial and insensitive search
if (!string.IsNullOrWhiteSpace(filters.SomeName))
query = query.Where(item => item.SomeName.IndexOf(filters.SomeName, StringComparison.OrdinalIgnoreCase) != -1);
// filter by multiple selection
if ((filters.CreatedByList?.Count ?? 0) > 0)
query = query.Where(item => filters.CreatedByList.Contains(item.CreatedById));
if (filters.EnabledOnly)
query = query.Where(item => item.IsEnabled);
var modelList = query.ToList();
var serviceModelList = MappingService.MapEx<SomeDataModel, SomeServiceModel>(modelList);
return serviceModelList;
}
Ưu điểm:
- truy vấn được tạo động dựa trên các bộ lọc được cung cấp. Không có thông số đánh hơi hoặc biên dịch lại gợi ý cần thiết
- dễ viết hơn cho những người trong thế giới OOP
- thông thường hiệu suất thân thiện, vì các truy vấn "đơn giản" sẽ được ban hành (mặc dù vẫn cần các chỉ mục thích hợp)
Nhược điểm:
- Các giới hạn LINQ2QL có thể đạt được và buộc hạ cấp xuống LINQ2Objects hoặc quay trở lại giải pháp SQL thuần túy tùy theo trường hợp
- Việc viết LINQ bất cẩn có thể tạo ra các truy vấn khủng khiếp (hoặc nhiều truy vấn, nếu thuộc tính điều hướng được tải)