我希望有比这更优雅的东西。这是我的存储过程解决方案。我蹩脚的 SQL 技能能想到的最好的东西。
参数列表中的 OUT 参数用于此集合中的总行数,因此前端知道有多少页与此特定过滤器集合一起。
CREATE PROC [dbo].[procCampaignGEDPushSelect]
@LastName VARCHAR(50) = null
,@FirstName VARCHAR(50) = null
,@Location VARCHAR(255) = null
,@DoB DateTime = null
,@Zip VARCHAR(50) = null
,@Phone VARCHAR(50) = null
,@Email VARCHAR(255) = null
,@Gender VARCHAR(20) = null
,@IsGED Bit = 0
,@IsBTT Bit = 0
,@IsOACE Bit = 0
,@Completed Bit = 0
,@TotalCount INT OUT
AS
BEGIN
SELECT @LastName = @LastName + '%'
SELECT @FirstName = @FirstName + '%'
SELECT @Location = @Location + '%'
SELECT @Zip = @Zip + '%'
SELECT @Phone = @Phone + '%'
SELECT @Email = @Email + '%'
SELECT @Gender = @Gender + '%'
SELECT row_number() OVER (ORDER BY LastName, FirstName, DoB) AS RowNumber
, TPT.LastName
, TPT.FirstName
, TPT.WF1Site
, TPT.DOB
, TPT.Zip
, TPT.Telephone
, TPT.CellPhone
, TPT.Email
, TPT.Gender
, TPT.IsBTT
, TPT.IsGED
, TPT.IsOACE
, TPT.IsSRS
,CGP.*
FROM tblCampaignGEDPush CGP
JOIN tblParticipants TPT
ON CGP.PartID = TPT.PartID
WHERE 1=1
AND 1 = (CASE WHEN @LastName IS NOT NULL THEN (CASE WHEN TPT.LastName LIKE @LastName THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @FirstName IS NOT NULL THEN (CASE WHEN TPT.FirstName LIKE @Firstname THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @Location IS NOT NULL THEN (CASE WHEN TPT.WF1Site LIKE @Location THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @Zip IS NOT NULL THEN (CASE WHEN TPT.Zip LIKE @Zip THEN 1 ELSE 0 END) ELSE 1 END)
AND
( 1 = (CASE WHEN @Phone IS NOT NULL THEN (CASE WHEN TPT.Telephone LIKE @Phone THEN 1 ELSE 0 END) ELSE 1 END)
OR 1 = (CASE WHEN @Phone IS NOT NULL THEN (CASE WHEN TPT.CellPhone LIKE @Phone THEN 1 ELSE 0 END) ELSE 1 END)
)
AND 1 = (CASE WHEN @Email IS NOT NULL THEN (CASE WHEN TPT.Email LIKE @Email THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @Gender IS NOT NULL THEN (CASE WHEN TPT.Gender LIKE @Gender THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @DoB IS NOT NULL THEN (CASE WHEN TPT.DoB = @DoB THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @IsGED != 0 THEN (CASE WHEN TPT.IsGED = 1 THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @IsBTT != 0 THEN (CASE WHEN TPT.IsBTT = 1 THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @IsOACE != 0 THEN (CASE WHEN TPT.IsOACE = 1 THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @Completed != 0 THEN (CASE WHEN CGP.Completed = 1 THEN 1 ELSE 0 END) ELSE 1 END)
ORDER BY TPT.LastName
, TPT.FirstName
, TPT.DoB
SELECT @TotalCount = @@ROWCOUNT
END
于是我开始思考。由于我在 .NET 中,所以我不使用这个棘手的、容易出错的过程(顺便说一句,它工作得很好),我想知道那里是否有一个很好的紧凑解决方案。
现在我知道最初的问题与 .NET 无关,所以我将上面的过程留给那些对严格的 SQL 解决方案感兴趣的人,我认为它工作得很好。
所以我开始深入研究 IQueryable 接口并获得了成功:
IQueryable<queryParticipant> qparticipant = db.queryParticipants.AsQueryable();
...
qparticipant = qparticipant.Where( ... any filter you choose );
...
return qparticipant
.OrderBy( p => p.LastName )
.OrderBy( p => p.FirstName )
.OrderBy( p => p.DOB )
.Select( ... whatever you like ... )
.Skip( StartRecordNumber ) // This is the trick! Start the query here..
.Take( PageSize ) // Take only as many as you need
;
就是这样。如果可用,.NET 方法很好。当这样的 API 不可用时,存储过程非常棒。