C# 如何将多个参数传递到.net core 3.1上的存储过程

C# 如何将多个参数传递到.net core 3.1上的存储过程,c#,sql-server,asp.net-core,.net-core,C#,Sql Server,Asp.net Core,.net Core,我在几年前写过一个函数,在迁移到.NETCore3.1之前一直工作得很好。现在参数尚未传递到SQL Server。我的职能是: public async Task<IList<string>> GetTree(GetPayload payload) { var cx = this.uow.Repository<Organization>().Context; var parameters = new List<SqlParameter&

我在几年前写过一个函数,在迁移到.NETCore3.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
}
在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

执行以下代码时,
@parentId
@perId
@isDeleted
的值将作为
NULL
传递。调用存储过程时,必须在
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;
}
public异步任务GetTree(GetPayload有效负载)
{
var cx=this.uow.Repository().Context;
var参数=新列表();
if(string.IsNullOrEmpty(payload.Code)==false)
parameters.Add(新的SqlParameter(“@code”,payload.code));
其他的
parameters.Add(新的SqlParameter(@code),DBNull.Value));//在这里修改了代码
if(payload.ParentId.IsNullOrEmpty()==false)
Add(新的SqlParameter(“@parentId”,payload.parentId));
其他的
parameters.Add(newsqlparameter(“@parentId”,DBNull.Value));//在这里修改了代码
//对@perId、@isDeleted参数执行相同操作。
//如果它们不存在于您的有效负载中,则直接将它们作为NULL传递
//Add(新的SqlParameter(“@perId”,DBNull.Value));
//Add(新的SqlParameter(“@isDeleted”,DBNull.Value));
var orgRes=await cx.Organization.FromSqlRaw(“SP_GetOrganization”,parameters.ToArray()).toListSync();
回归原初;
}

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

如果其中一个参数可以为null,请检查如下:

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();
然后调用如下过程:

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需要这些参数

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;
}

多亏了Sowmyadhar Gourishetty和Panagiotis Kanavos,文档非常清晰。也不需要使用
ToArray()
,甚至不需要使用列表。
parameters
参数是一个
params
数组,这意味着您可以直接传递任意数量的参数值。不管问题是什么,都与传递多个参数sif(string.IsNullOrEmpty(payload.Code)==false)等无关-有效负载可以吗?顺便说一句,您不需要写“==false”,只要(!string.IsNullOrEmpty(payload.Code))我怀疑数据访问代码是不必要的卷积。首先,不需要显式的工作单元或存储库。DbContext是一个工作单元,DbSet是一个存储库。试图找回UoW中隐藏的上下文意味着代码已经泄漏。为什么要使用该存储过程,为什么要使用可变参数?您是否正在尝试使用全面查询?如果只是根据需要将LINQ与不同的
.Where()
子句一起使用,则根本不需要这样做。一网打尽的查询也会损害性能,LINQ是一种避免这种情况的方法that@SeattlePigeon除了说数据访问代码看起来。。。麻烦的发布存储过程并检查实际内容。你让人们猜测看不见的代码。我怀疑真正的解决方案是抛弃不必要的自定义UoW和存储库,使用EF Coreproperly@SeattlePigeon在另一个已经提供的UoW和repository之上使用UoW和“repositories”(实际上是数据访问对象)是一种丑陋的反模式,早在2009年就被主要ORM作者发现了。EF Core不需要它们,我不确定存储过程中是否有额外的逻辑。如果是直接
组织
表中选择
,我建议使用
LINQ
。例如:
。其中(x=>x.code==payload.code)
仍然相同。结果永远不会随过滤器而改变:/