我正在使用Dapper
' QueryMultipleAsync
方法来读取多个结果集。我的存储过程检查某些条件(例如,用户可能通过向我的API发送Id来尝试获取其他人的数据)以确定数据是否应该返回。
我,在C#方面,首先需要读取return value
(不是结果集)来确定是否返回数据或者只返回SP 3(这意味着权利不足)。为了说明这个案例:
IF @UserRole < 10
BEGIN
RETURN 3; -- Insufficient rights.
END
IF @IsCurrentUserOwner = 0
BEGIN
RETURN 5; -- Not owner.
END
-- Get users.
SELECT
Id
, [Name]
, LastName
FROM
Users
-- WHERE ...
-- Get chat messages.
SELECT
*
FROM
ChatMessages
-- WHERE ...
我知道output
和return
值写在读者的末尾,因此我只能在读取所有数据(结果集)时读取返回参数。所以,我总是先读取结果集然后返回/输出参数。
如果我的SP
看起来像这样:
-- ...some code above...
IF @IsCurrentUserOwner = 0
BEGIN
RETURN 5; -- Not owner.
END
DECLARE @RType TINYINT = NULL
-- some other code here to get @RType value here...
SELECT @RType -- To make this a result so QueryMultiple's reader can read this.
-- ...some other code to get users and chat messages...
描述问题:
@RType
变量可以是5
以及SP
的返回值。当我首先读取结果时(因为输出/返回参数位于读者的末尾),我怎么知道我刚刚读取的值(在这种情况下是5
)是@RType还是返回值? (他们是可兑换的)
这就是我的C#代码大致如下:
var parameters = new DynamicParameters();
parameters.Add("@RetVal", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
var dbResult = await Context.SqlConnection.QueryMultipleAsync(sql: "my_sp_name", param: parameters, commandType: CommandType.StoredProcedure)
// Some code here...
using (var reader = dbResult)
{
var rType = reader.Read<byte>(); // <----- How to know if I read @RType or just return value of SP since they are convertible to each other?
var users = reader.Read<User>();
var chatMessages = reader.Read<ChatMessage>();
// ...
}
var returnValue = parameters.Get<int>("@RetVal");
if (returnValue == 5)
{
return "You are not allowed to see this data";
}
你怎么建议我处理这个案子?
答案 0 :(得分:0)
您的C#代码使用async - await(QueryMultipleAsync),目前Dapper不支持不执行SELECT语句的Async方法。 在Github中存在一个未解决的问题: https://github.com/StackExchange/Dapper/issues/591
选项1
您可以将存储过程拆分为两部分:
1.检查返回值
2.获取选择陈述
选项2
ALTER PROCEDURE dbo.sp
... your params..
@Output INT OUTPUT
AS
IF @UserRole < 10
BEGIN
SET @Output = 3; -- Insufficient rights.
END
IF @IsCurrentUserOwner = 0
BEGIN
SET @Output = 5; -- Not owner.
END
-- Get users.
SELECT
Id
, [Name]
, LastName
FROM
Users
-- WHERE ...
-- Get chat messages.
SELECT
*
FROM
ChatMessages
-- WHERE ...
选项3
使用ADO.NET
答案 1 :(得分:0)
我对你的问题并不是很清楚,但下面的代码段应该可行。由于您将@RetVal定义为ParameterDirection.ReturnValue,因此您应该能够在访问实际读者之前访问它。我能够在SQL SERVER中验证这是有效的。
var returnValue = parameters.Get<int>("@RetVal");
if (returnValue == 5 || returnValue == 3)
{
return "You are not allowed to see this data";
}
using (var reader = dbResult)
{
var rType = reader.Read<byte>(); // <----- How to know if I read @RType or just return value of SP since they are convertible to each other?
var users = reader.Read<User>();
var chatMessages = reader.Read<ChatMessage>();
// ...
}
这是我的存储过程
ALTER PROCEDURE mysp_TestOne
@p1 int
AS
BEGIN
SET NOCOUNT ON;
if @p1 > 0
return 5;
SELECT 1 F1
union
Select 2 F1;
SELECT 1 F1
union
Select 2 F1;
END
GO
更完整的c#片段;
using (SqlConnection cn = new SqlConnection(connectionString))
{
var sql = @"mysp_TestOne";
var parameters = new DynamicParameters();
// @p1 triggers whether to return query results or just the returnvalue
parameters.Add("p1", 0, direction: ParameterDirection.Input);
parameters.Add("@RetVal", 0, direction: ParameterDirection.ReturnValue);
var dbResult = await cn.QueryMultipleAsync(sql, parameters, commandType: CommandType.StoredProcedure);
var returnValue = parameters.Get<int>("@RetVal");
if (returnValue == 5 || returnValue == 3)
{
return "You are not allowed to see this data";
}
using (var reader = dbResult)
{
var rType = reader.Read<byte>(); // <----- How to know if I read @RType or just return value of SP since they are convertible to each other?
var users = reader.Read<User>();
var chatMessages = reader.Read<ChatMessage>();
// ...
}
}
HTH