【问题标题】:How to pass multiple parameters to stored procedure on .net core 3.1如何将多个参数传递给.net core 3.1上的存储过程
【发布时间】:2020-12-15 03:46:12
【问题描述】:

我在几年前编写了一个函数,并且在迁移到 .NET Core 3.1 之前一直运行良好。现在参数还没有传递给 SQL Server。我的功能是:

public async Task<IList<string>> GetTree(GetPayload payload)
{
    var cx = this.uow.Repository<Organization>().Context;

    var parameters = new List<SqlParameter>();

    if (string.IsNullOrEmpty(payload.Code) == false)
        parameters.Add(new SqlParameter("@code", payload.Code));

    if (payload.ParentId.IsNullOrEmpty() == false)
        parameters.Add(new SqlParameter("@parentId", payload.ParentId));
    
    var orgRes = await cx.Organization.FromSqlRaw("SP_GetOrganization", parameters.ToArray()).ToListAsync();
  
    return orgRes
}

调试这段代码时,参数成功地传到API。但是当用'FromSqlRaw' 调用SQL 时,参数显示为'0'。为什么?

这是我的存储过程:

DECLARE @RC int
DECLARE @code nvarchar(50)
DECLARE @parentId uniqueidentifier
DECLARE @perId uniqueidentifier
DECLARE @isDeleted bit

-- TODO: Set parameter values here.

EXECUTE @RC = [dbo].[SP_GetOrgTree] 
   @code
  ,@parentId
  ,@perId
  ,@isDeleted
GO

在 SQL 中,当像这样编辑代码时:程序运行没有问题。如何在 EF Core 中解决此问题?

DECLARE @RC int
    DECLARE @code nvarchar(50)
    DECLARE @parentId uniqueidentifier
    DECLARE @perId uniqueidentifier
    DECLARE @isDeleted bit
    
    SET @code = 'sample code'
    
    EXECUTE @RC = [dbo].[SP_GetOrgTree] 
       @code
      ,@parentId
      ,@perId
      ,@isDeleted
    GO

【问题讨论】:

  • 文档很清楚。也不需要使用ToArray(),甚至不需要使用列表。 parameters 参数是一个params 数组,这意味着您可以直接传递任意数量的参数值。无论问题是什么,都与传递多个参数无关
  • if (string.IsNullOrEmpty(payload.C​​ode) == false) 等 - 有效载荷可以吗?顺便说一句,你不需要写“==false”,只要 (!string.IsNullOrEmpty(payload.C​​ode))
  • 我怀疑数据访问代码是不必要的复杂。对于初学者来说,不需要明确的工作单元或存储库。 DbContext is 一个工作单元,一个 DbSet is 一个存储库。试图取回隐藏在 UoW 中的上下文意味着代码已经泄漏。为什么要使用该存储过程,为什么要使用可变参数?您是否尝试使用包罗万象的查询?如果您只是根据需要使用带有不同 .Where() 子句的 LINQ,则根本不需要这样做。一个包罗万象的查询也危害性能,而 LINQ 是一种避免这种情况的方法
  • @SeattlePigeon 不可能猜到哪里出了问题,除了说数据访问代码看起来......很麻烦。发布存储过程并检查实际内容。您是在要求人们猜测不可见的代码。我怀疑真正的解决方案是放弃不需要的自定义 UoW 和存储库,并正确使用 EF Core
  • @SeattlePigeon 在另一个已经提供的 UoW 和存储库之上使用 UoW 和“存储库”(实际上是数据访问对象)是一种丑陋的模式,早在2009 年由 ORM 主要作者撰写。 Repository is the new Antipattern。 EF Core 不需要它们 -No need for repositories and Unit of Work with EF Core

标签: c# sql-server asp.net-core .net-core


【解决方案1】:

当您执行以下代码时,@parentId@perId@isDeleted 的值将作为NULL 传递。当您调用 SPROC 时,您必须从 c# 执行相同的操作。

DECLARE @RC int
DECLARE @code nvarchar(50)
DECLARE @parentId uniqueidentifier
DECLARE @perId uniqueidentifier
DECLARE @isDeleted bit

SET @code = 'sample code'

EXECUTE @RC = [dbo].[SP_GetOrgTree] 
   @code
  ,@parentId
  ,@perId
  ,@isDeleted
GO

请参阅下面的代码以传递NULL 值。我正在修改相同的代码。请对其他两个参数执行相同操作。

public async Task<IList<string>> GetTree(GetPayload payload)
{
    var cx = this.uow.Repository<Organization>().Context;

    var parameters = new List<SqlParameter>();

    if (string.IsNullOrEmpty(payload.Code) == false)
        parameters.Add(new SqlParameter("@code", payload.Code));
    else
        parameters.Add(new SqlParameter("@code", DBNull.Value)); // Modified the code here

    if (payload.ParentId.IsNullOrEmpty() == false)
        parameters.Add(new SqlParameter("@parentId", payload.ParentId));
    else
        parameters.Add(new SqlParameter("@parentId", DBNull.Value)); // Modified the code here

    // Do the same for @perId, @isDeleted parameters. 
    // If they don't exist in your payload, just pass them as NULL directly

    // parameters.Add(new SqlParameter("@perId", DBNull.Value));
    // parameters.Add(new SqlParameter("@isDeleted", DBNull.Value));

    var orgRes = await cx.Organization.FromSqlRaw("SP_GetOrganization", parameters.ToArray()).ToListAsync();

    return orgRes;
}

【讨论】:

  • 我不确定您是否在 SPROC 中有一些额外的逻辑。如果是直接来自Organization 表的Select,我建议使用LINQ。例如:.Where(x =&gt; x.Code == payload.Code)
  • 还是一样。结果永远不会随着过滤器而改变。 ://
【解决方案2】:

终于解决了我的问题。非常感谢各位。答案如下:

如果一个参数可以为空,检查如下:

if (string.IsNullOrEmpty(payload.Code) == false)
    parameters.Add(new SqlParameter("@code", payload.Code));
else
    parameters.Add(new SqlParameter("@code", DBNull.Value));

并像这样调用程序:

var orgRes = await cx.PdOrganizationTreeQuery
                   .FromSqlRaw("SP_Organization @code,@parentId,@perId,@isDeleted", parameters: parameters.ToArray())
                   .ToListAsync();

注意:所有参数必须写入 FromSqlRaw()。因为 SQL Server 需要这些参数。

感谢 Sowmyadhar Gourishetty 和 Panagiotis Kanavos

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-23
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 2016-04-05
    相关资源
    最近更新 更多