晚了五年。
在接受的答案的提供的链接中提到了它,但是我认为它应该在SO上有一个明确的答案-根据提供的参数动态构建查询。例如:
建立
-- 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
程序
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
用法
exec spDoSearch @TopCount = 3
exec spDoSearch @FirstName = 'Dick'
优点:
- 易于编写和理解
- 灵活性-轻松生成查询以进行更棘手的过滤(例如,动态TOP)
缺点:
不是直接的答案,而是与问题有关
通常,这些筛选存储过程不会浮动,而是从某些服务层调用。这样就可以选择将业务逻辑(过滤)从SQL移到服务层。
一个示例是使用LINQ2SQL根据提供的过滤器生成查询:
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;
}
优点:
- 根据提供的过滤条件动态生成的查询。没有参数嗅探或重新编译提示
- 为OOP世界中的人写些容易
- 通常性能友好,因为将发出“简单”查询(尽管仍然需要适当的索引)
缺点:
- 可能会达到LINQ2QL限制,并根据情况强制降级到LINQ2Objects或返回纯SQL解决方案
- 粗心地编写LINQ可能会生成可怕的查询(如果加载了导航属性,则可能会生成许多查询)