죄송합니다. 함수, 기간에 동적 SQL을 수행 할 수 없습니다. 동적 SQL을 필요로하지 않는 함수를 다시 작성할 수는 있지만 근본적인 문제를 실제로 해결할 수 있습니까? 에 절차가 필요하고 반환 유형과 관련된 전혀 관련이없는 Entity Framework 문제로 인해 여전히 손수갑 일 때 무엇을 할 것입니까? 분명히 EF를 구성했거나 프로 시저를 연결 한 방식이 잘못되었거나 그렇지 않은 경우 lot 사람이 결과 집합을 반환하는 절차에서 EF가 작동하지 않는다고 불평 할 것입니다. 그럴 것 같니?
CREATE FUNCTION dbo.GetLogApiCalls -- dbo prefix, always
(
@displayStart INT,
@displayLength INT, -- is this a page size, like 20, or @displayEnd?
@searchString NVARCHAR(1000),
@orderBy NVARCHAR(100),
@orderByDirection VARCHAR(4)
)
RETURNS TABLE
AS -- make it an inline TVF. Multi-statement TVFs can be a perf nightmare.
RETURN
(
SELECT * FROM
(
SELECT rn = ROW_NUMBER() OVER (ORDER BY
CASE @orderByDirection WHEN 'ASC' THEN
CASE @orderBy WHEN N'Provider' THEN Provider
WHEN N'RequestData' THEN RequestData
WHEN N'ResponseData' THEN ResponseData
WHEN N'UserName' THEN UserName
WHEN N'AccountName' THEN AccountName
WHEN N'MethodName' THEN MethodName
WHEN N'RequestIdentifier'
THEN CONVERT(CHAR(36), RequestIdentifier)
WHEN N'CreatedDate' THEN CONVERT(CHAR(23), CreatedDate, 126)
END
END,
CASE @orderByDirection WHEN 'ASC' THEN
CASE @orderBy WHEN N'Id' THEN Id
WHEN N'AccountId' THEN AccountId
WHEN N'CreatedUserId' THEN CreatedUserId
END
END,
CASE @orderByDirection WHEN 'DESC' THEN
CASE @orderBy WHEN N'Provider' THEN Provider
WHEN N'RequestData' THEN RequestData
WHEN N'ResponseData' THEN ResponseData
WHEN N'UserName' THEN UserName
WHEN N'AccountName' THEN AccountName
WHEN N'MethodName' THEN MethodName
WHEN N'RequestIdentifier'
THEN CONVERT(CHAR(36), RequestIdentifier)
WHEN N'CreatedDate' THEN CONVERT(CHAR(23), CreatedDate, 126)
END
END DESC,
CASE @orderByDirection WHEN 'DESC' THEN
CASE @orderBy WHEN N'Id' THEN Id
WHEN N'AccountId' THEN AccountId
WHEN N'CreatedUserId' THEN CreatedUserId
END
END DESC), [Id],[Provider],[RequestIdentifier],[RequestData],
[ResponseData],[UserName],[AccountName],[AccountId],
[CreatedUserId],[CreatedDate],[MethodName]
FROM dbo.LogAPICall
WHERE LEN(@searchString) = 0 OR
(
@searchString > '' AND
(
Provider LIKE '%' + @searchString + '%'
OR MethodName LIKE '%' + @searchString + '%'
)
)
) AS x
WHERE rn BETWEEN @displayStart AND @displayStart + @displayLength - 1 -- assumption
);
이 동적 인 ORDER BY
은 악마입니다. 인라인 TVF인데도 조회를 수행하고 OPTION (RECOMPILE)
을 추가하여 다른 매개 변수에 대해서만 잘 수행됩니다. 해결책? 동적 SQL과 함께 저장 프로 시저를 사용하고 Entity Framework 구성 문제를 별도로 파악하십시오.
CREATE PROCEDURE dbo.GetLogApiCalls -- dbo prefix, always
@displayStart INT,
@displayLength INT, -- is this a page size, like 20, or @displayEnd?
@searchString NVARCHAR(1000),
@orderBy NVARCHAR(100),
@orderByDirection VARCHAR(4)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX) = N'SELECT * FROM (
SELECT rn = ROW_NUMBER() OVER (ORDER BY '
+ @orderBy + ' ' + @orderByDirection + '),
[Id],[Provider],[RequestIdentifier],[RequestData],
[ResponseData],[UserName],[AccountName],[AccountId],
[CreatedUserId],[CreatedDate],[MethodName]
FROM dbo.LogAPICall'
+ CASE WHEN LEN(@searchString) > 0 THEN
' WHERE Provider LIKE ''%'' + @searchString + ''%''
OR MethodName LIKE ''%'' + @searchString + ''%'''
ELSE '' END
+ ') AS x
WHERE rn BETWEEN @displayStart
AND @displayStart + @displayLength - 1;';
DECLARE @params NVARCHAR(MAX) = N'@searchString NVARCHAR(1000),'
+ '@displayStart INT, @displayLength INT';
EXEC sp_executesql @sql, @params, @searchString, @displayStart, @displayLength;
END
GO
당신이 설정 optimize for ad hoc workloads
가 활성화 한 경우에 특히 : 저장 프로 시저로이 훨씬 더 같은 것입니다. 이제는 매개 변수화 할 수없는 동적 ORDER BY로 인해 SQL 인젝션이 발생하기 쉽기 때문에이 매개 변수에 유효한 값만 포함되어 있는지 확인을 추가 할 수 있습니다.
[또한 길이가없는'varchar' 선언을 중단하십시오] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring-varchar-without- length.aspx) 및 [개체를 만들거나 참조 할 때 항상 스키마 접두사를 사용합니다.] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/11/bad-habits-to-kick-avoiding-the- schema-prefix.aspx). –
알겠습니다.이 사실을 명심하십시오. 덕분에 – sanjeev