我有一个用 LINQ 编写的 EF Core 8 查询,如下所示并产生预期结果。下面,
branchIds
是 list
的 string
。
bool hasAccess = await _dbContext.Set<UserAssignedBranch>()
.Where(w => w.AgentId == agentId &&
branchIds.All(a => a == w.BranchId) &&
w.AppUserId == userId)
.AnyAsync();
一旦执行,我就会得到预期的输出。
我想将其转换为存储过程。因此,我打开 SQL Server Profiler 并从 EF Core 获取翻译后的 SQL 语法,如下所示:
exec sp_executesql N'SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [UserAssignedBranch] AS [u]
WHERE [u].[AgentId] = @__agentId_0 AND NOT EXISTS (
SELECT 1
FROM OPENJSON(@__branchIds_1) WITH ([value] uniqueidentifier ''$'') AS [b]
WHERE [b].[value] <> [u].[BranchId]) AND [u].[AppUserId] = @__userId_2) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END',N'@__agentId_0 uniqueidentifier,@__branchIds_1 nvarchar(4000),@__userId_2 uniqueidentifier',@__agentId_0='FB4426D2-F237-4F7B-FA9C-08DC2CABC414',@__branchIds_1=N'["684a6a00-0a73-4c23-f525-08dc2cabc427","5a29f7fe-3fc0-42cb-a946-e3b73e09ca13"]',@__userId_2='DBEF4707-F497-43DF-9D27-08DC2CABC51B'
我尝试从此编写存储过程,这导致了以下代码:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_CheckBranchAccess]
@UserId NVARCHAR(100),
@AgentId NVARCHAR(100),
@BranchIds NVARCHAR(MAX) = N'[]'
AS
BEGIN
DECLARE @Result BIT;
SELECT @Result = CASE
WHEN EXISTS (
SELECT 1
FROM [UserAssignedBranch] AS [u]
WHERE [u].[AgentId] = @AgentId AND NOT EXISTS (
SELECT 1
FROM OPENJSON(@BranchIds) WITH ([value] UNIQUEIDENTIFIER '$') AS [b]
WHERE [b].[value] = [u].[BranchId]
) AND [u].[AppUserId] = @UserId
) THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT)
END;
SELECT @Result AS [Result];
END
这就是我从 C# 调用存储过程的方式:
var strbranchIds = branchIds.Select(s => s.ToString()).ToList();
List<SqlParameter> parms = new()
{
new SqlParameter { ParameterName = "@AgentId", Value = agentId.ToString() },
new SqlParameter { ParameterName = "@UserId", Value = userId.ToString() },
new SqlParameter { ParameterName = "@BranchIds", Value = string.Join(',',strbranchIds ?? new List<string>()) }
};
var hasClaim = await _dbContext.Set<SP_CheckBranchAccess>()
.FromSqlRaw("EXEC SP_CheckBranchAccess @AgentId, @UserId, @BranchIds", parms.ToArray())
.ToListAsync(cancellationToken: token);
但在这种情况下,我没有得到 LINQ-to-SQL 的预期结果。有人能帮我解决这个问题吗?
请勿使用
.Set<T>.FromSqlRaw
,因为这旨在从 SQL 返回并填充实体定义。在您的情况下,您实际上只需要 True/False 的标量值。相反,请尝试使用所需参数(包括结果的 OUTPUT 参数)_dbContext.Database.ExecuteSqlCommand
。