パーティーに5年遅れました。
それは、受け入れられた回答の提供されたリンクで言及されていますが、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からサービスレイヤーに移動することができます。
1つの例は、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の記述により、ひどいクエリ(またはナビゲーションプロパティが読み込まれている場合は多くのクエリ)が生成される可能性があります。