EF Core 8 LINQ转存储过程结果不符,请求修正
问题分析与修正方案
你的问题出在两个关键环节:存储过程逻辑与原LINQ不一致,以及C#调用时分支ID参数格式错误,以下是具体修正步骤:
1. 修正存储过程的逻辑错误
原LINQ中的branchIds.All(a => a == w.BranchId),EF Core生成的SQL逻辑是NOT EXISTS (SELECT 1 FROM OPENJSON(...) WHERE [b].[value] <> [u].[BranchId])——意思是「分支列表中不存在与当前记录BranchId不相等的项」,即所有分支ID都匹配当前记录的BranchId。
但你编写的存储过程错误地将条件写成WHERE [b].[value] = [u].[BranchId]后加NOT EXISTS,完全反转了原逻辑。同时,参数类型应与数据库字段一致(用UNIQUEIDENTIFIER而非NVARCHAR(100)),避免类型转换问题。
修正后的存储过程:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[SP_CheckBranchAccess] @UserId UNIQUEIDENTIFIER, @AgentId UNIQUEIDENTIFIER, @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
2. 修正C#调用的参数格式与顺序错误
EF Core生成的SQL中,分支ID参数是JSON数组格式(如["xxx","xxx"]),但你当前用string.Join(',', strbranchIds)生成的是逗号分隔字符串,会导致OPENJSON无法正确解析。此外,存储过程参数顺序与调用时的顺序不匹配,会导致参数传递错位。
修正后的C#调用代码:
// 将分支ID序列化为JSON数组格式 var branchIdsJson = System.Text.Json.JsonSerializer.Serialize(branchIds ?? new List<string>()); List<SqlParameter> parms = new() { new SqlParameter { ParameterName = "@UserId", Value = userId }, // 按存储过程参数顺序传递 new SqlParameter { ParameterName = "@AgentId", Value = agentId }, new SqlParameter { ParameterName = "@BranchIds", Value = branchIdsJson } }; // 调用存储过程并获取结果 var result = await _dbContext.Set<bool>() .FromSqlRaw("EXEC SP_CheckBranchAccess @UserId, @AgentId, @BranchIds", parms.ToArray()) .FirstOrDefaultAsync(cancellationToken: token); // 若使用SP_CheckBranchAccess实体类,可改为: // var accessResult = await _dbContext.Set<SP_CheckBranchAccess>() // .FromSqlRaw("EXEC SP_CheckBranchAccess @UserId, @AgentId, @BranchIds", parms.ToArray()) // .FirstOrDefaultAsync(token); // bool hasClaim = accessResult?.Result ?? false;
额外注意点
- 直接传递
Guid类型参数而非字符串,减少类型转换的潜在问题; - 调用存储过程时,参数顺序必须与存储过程定义的顺序一致,或明确指定参数名(如
EXEC SP_CheckBranchAccess @UserId = @UserId, @AgentId = @AgentId, @BranchIds = @BranchIds),避免参数错位。
内容的提问来源于stack exchange,提问作者thanzeel
相关产品推荐
相关产品推荐

