在 .NET Core 3.1 中执行存储过程
Posted
技术标签:
【中文标题】在 .NET Core 3.1 中执行存储过程【英文标题】:Execute Stored Procedure in .NET Core 3.1 【发布时间】:2021-11-05 17:42:29 【问题描述】:我正在尝试在 ASP.NET Core 3.1 中运行 SQL Server 2019 存储过程,但无法正常运行。
我已经实现了存储库布局模式,并使用以下命令获取了数据库对象:
Scaffold-DbContext "Server="";Database="";User ID="";Password="";" Microsoft.EntityFrameworkCore.SqlServer -OutputDir database
执行程序时,如果结果是用户存在于数据库中,则应该返回1,否则返回0。总是返回1给变量“exists”的问题,但我想我是不执行存储过程(它有一个输出参数)或者我不知道该过程是否需要以某种方式导入到应用程序中。
程序示例:
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
非常感谢您的帮助。
教程
【问题讨论】:
entityframeworktutorial.net/efcore/… 我对这些命令进行了测试,但它表明它们在 NetCore 3.1 中已被弃用。谢谢 我发现的另一个不一致之处,在您的store procedure
中有 RETURN
它不应该返回任何内容,因为在 store procedure
中我们必须使用 SELECT
声明,我怀疑您的 sp
可以以这种方式返回1
或0
,另一件事是您已经定义了3 个参数但传递了2 个应该引发期望的参数,我认为根据您的情况,您应该在sp
正文中写DECLARE @EXIT INT
而不是定义它。
有 3 种方法可以从存储过程中返回信息:返回值 - 应该只用于指示操作的状态,而 not 用于返回业务逻辑,如“用户没有/ 不存在”,OUTPUT 参数发送单个值或一组值,选择一个结果集。你用错了..
旁白:请告诉您的新公司停止以纯文本形式存储密码!
【参考方案1】:
要按原样使用您的存储过程,您可能应该连接到输出参数。请注意,除了“生成 SqlConnection/命令的东西”之外,这并没有真正使用* 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;
记得添加必要的using
s..
*(AFAIA,没有方法可以;即使看起来像使用 EF Core 的方法也只是获取其 SQLBuilder 并构建一个调用存储过程的命令)
【讨论】:
【参考方案2】:ExecuteSqlRawAsync
返回插入、更新和删除受影响的行数(-1 表示选择)。
我建议您更改您的 SP 以删除输出参数,而是使用 SqlCommand. SqlCommand.ExecuteScalar()
返回结果集中第一行的第一列:
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 以编辑存储过程。
【讨论】:
以上是关于在 .NET Core 3.1 中执行存储过程的主要内容,如果未能解决你的问题,请参考以下文章
如何从 ASP.NET Core 3.1 中的存储库类创建确认电子邮件回调
在 ASP.NET MVC Core(C#) 中执行 Oracle 存储过程 (PL/SQL)
如何在 ASP.NET Core MVC 中使用 ADO.NET 向存储过程添加参数?
包含在FromSqlRaw和EF Core 3.1中的存储过程中
在 cookie 中存储 JWT 令牌后,如何在 ASP.NET Core 3.1 中破坏该 cookie 并获取信息
如何使用 FromSqlRaw Entity Framework Core 3.1 从存储过程中返回多个 SELECT 集