在 .NET Core 3.1 中执行存储过程

Execute Stored Procedure in .NET Core 3.1

我正在尝试 运行 SQL ASP.NET Core 3.1 中的 Server 2019 存储过程,但无法将它们正确地 运行。

我实现了存储库布局模式并使用以下命令获取了数据库对象:

Scaffold-DbContext "Server="";Database="";User ID="";Password="";" Microsoft.EntityFrameworkCore.SqlServer -OutputDir database

程序执行时,如果结果是用户存在于数据库中,应该return为1,否则为0。总是return给变量赋1的问题“存在”,但我想我没有执行存储过程(它有一个输出参数),或者我不知道是否需要以某种方式将该过程导入到应用程序中。

程序示例:

CREATE PROCEDURE [dbo].[LOGIN]
    @LOGIN    VARCHAR(50),  
    @PASSWORD VARCHAR(50),
    @EXIT     INT OUTPUT
BEGIN
    IF EXISTS (SELECT USER_APP FROM USERS 
               WHERE USER_APP = @LOGIN AND PASSWORD = @PASSWORD)
    BEGIN
        SET @EXIT = 1
        RETURN @EXIT
    END

    SET @EXIT = 0
    RETURN @EXIT
END

节目:

private readonly dbContext _context;

public UsuariosRepository(dbContext context)
{
    _context = context;
}

public async Task<bool> lOG(string user, string password)
{ 
    try
    {
        int exists= await _context.Database.ExecuteSqlRawAsync("EXECUTE Login {0},{1}", user, password);

        return exists > 0;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

根据我在以下位置找到的教程,使用我目前拥有的代码更新问题:

https://erikej.github.io/efcore/2020/11/02/ef-core-sproc-return-value.html

var retcode = new SqlParameter
{
    ParameterName = "0",
    SqlDbType = System.Data.SqlDbType.Int,
    Direction = System.Data.ParameterDirection.Output,
    Value=0
};
var result =  _context.Database.ExecuteSqlRaw("EXEC Login {0},{1},{2}", usuario, password,retcode);

int returnValue = (int)retcode.Value;

即使进行了更改,它对我也不起作用,它显示以下错误。

Unable to cast object of type 'System.DBNull' to type 'System.Int32

非常感谢您的帮助。

教程

ExecuteSqlRawAsync returns 插入、更新和删除受影响的行数(选择为 -1)。

我建议您更改 SP 以删除输出参数,而是使用 SqlCommand. SqlCommand.ExecuteScalar() 到 return 结果集中第一行的第一列:

using (var cmd = _context.Database.GetDbConnection().CreateCommand()) {
    cmd.CommandText = "[dbo].[LOGIN]";
    cmd.CommandType = System.Data.CommandType.StoredProcedure;
    if (cmd.Connection.State != System.Data.ConnectionState.Open) cmd.Connection.Open();
    cmd.Parameters.Add(new SqlParameter("LOGIN", user));
    cmd.Parameters.Add(new SqlParameter("PASSWORD", password));
    exists = (int)cmd.ExecuteScalar();
}

只需将@EXIT 声明为不作为输出即可,例如:

CREATE PROCEDURE [dbo].[LOGIN]
    @LOGIN      VARCHAR(50),    
    @PASSWORD   VARCHAR(50) 

    DECLARE @EXIT INT

并将 CREATE 替换为 ALTER 以编辑存储过程。

要按原样使用存储过程,您可能应该连接到输出参数。请注意,除了“生成 SqlConnection/command 的东西”之外,这并没有真正使用 * EF Core:


string user = "bob";
string password = Convert.ToBase64tring(Sha256Hash("secret", "mmmmsalty"));// you salt and hash your passwords, right??


using var cmd = _context.Database.GetDbConnection().CreateCommand();
cmd.CommandText = "[dbo].[LOGIN]";

//common
cmd.CommandType = CommandType.StoredProcedure;
if (cmd.Connection.State != ConnectionState.Open) cmd.Connection.Open();
cmd.Parameters.Add(new SqlParameter("@LOGIN", SqlDbType.VarChar) { Value = user });
cmd.Parameters.Add(new SqlParameter("@PASSWORD", SqlDbType.VarChar) { Value = password });
cmd.Parameters.Add(new SqlParameter("@EXIT", SqlDbType.Int) { Direction = ParameterDirection.Output });

cmd.ExecuteNonQuery();

var userExists = (int)cmd.Parameters["@EXIT"].Value == 1;

记得添加必要的usings..

*(AFAIA,没有方法;即使是看起来像使用 EF Core 的方法也只是获取其 SQLBuilder 并构建一个调用存储过程的命令)