【问题标题】:Why does calling a T-SQL function using Entity Framework Core always return -1?为什么使用 Entity Framework Core 调用 T-SQL 函数总是返回 -1?
【发布时间】:2021-06-18 00:08:58
【问题描述】:

如果这很重要,我正在使用 ASP.NET Core 和 C#。当我在控制器中到达以下行时:

var validLogin = context.Database.ExecuteSqlRaw($"SELECT * FROM dbo.[valid_login]('{username}','{password}')");

我总是会得到 -1 的回报。我还使用了ExecuteSqlCommand 并得到了相同的结果。我尝试创建表定义函数和标量函数,无论哪种情况,它都只返回-1。

最奇怪的是它可以在 SSMS 中运行。当我点击 breakpiont 时,这是正在发送的查询:

{SELECT * FROM dbo.[valid_login]('test@email.com','password')}

当我在 SSMS 中运行它时,我得到正确的结果 1。如果重要的话,这里是该函数的最新版本。但就像我说的那样,我使用标量函数得到完全相同的结果。

ALTER FUNCTION valid_login
    (@email varchar(1000), 
     @password varchar(1000))
RETURNS TABLE 
AS
    RETURN 
        (SELECT 
             CASE WHEN (SELECT COUNT(*) FROM [user] 
                        WHERE @email = email_address 
                          AND HASHBYTES('SHA2_512', CONCAT(password_salt, @password)) = password_hash) = 1
                     THEN 1
                     ELSE 0
             END AS valid)
GO

显然,必须发生两件事中的一件。 Entity Framework Core 在运行之前更改了我的 SQL 代码,或者我没有使用正确的方法从函数中获取结果。我不认为这是第二个,因为我没有看到简单的context.Database.RunSqlFunction() 方法或类似的方法。如果这是第一个,我的知识还不够丰富,不知道为什么会这样。

真的,我只需要知道如何使用 Entity Framework Core 在 ASP.NET Core 中获取 T-SQL 函数的结果。因此,如果您能告诉我最简单的方法,或者我需要进行哪些修改才能使其正常工作,我们将不胜感激。

【问题讨论】:

  • 旁注:散列密码客户端并通过散列。使用EXISTS 而不是COUNT... = 1
  • 因为 EF 调用总是最终解析为 DbCommand.ExecuteNonQuery 方法 (docs.microsoft.com/en-us/dotnet/api/…) 并且根据 Microsoft 上的文档“对于 UPDATE、INSERT 和 DELETE 语句,返回值是行数受命令影响。对于所有其他类型的语句,返回值为-1。"

标签: c# sql .net-core entity-framework-core asp.net-core-mvc


【解决方案1】:

你总是得到 1 ,因为它是所选行数。

如果你想从数据库中获取一些数据,你必须使用这个算法:

  1. 创建一个特殊的类来从 sp 中获取数据。此类应具有您在查询字符串中选择的所有属性。您无需选择所有内容。只需选择您需要的。

    public class ResultData
    {
    public string Property1 {get;set;}
    public string Property2 {get;set;}
    .....
    .....
    }
    
  2. 添加到 dbContext ResultData DbSet 并配置没有这样的键

    public virtual DbSet<ResultData> ResultData { get; set; }
    
    ....
    
    modelBuilder.Entity<ResultData>(e =>
            {
                e.HasNoKey();
            });
    
  3. 这是一个获取数据的示例函数

    public async Task<IEnumerable<ResultData>> GetData(int id, string name)
    {
        return await _context.Set<ResultData>()
                 .FromSqlInterpolated($"SELECT  Property1, Property2 FROM dbo.[valid_login]('{username}','{password}')")
                .ToArrayAsync();
    }
    

我强烈建议您使用参数而不是字符串值。

【讨论】:

    猜你喜欢
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    • 2017-09-24
    • 1970-01-01
    • 2019-08-16
    • 2019-06-26
    • 2020-02-22
    相关资源
    最近更新 更多