【问题标题】:ASP.NET core get count from a table using raw queryASP.NET 核心使用原始查询从表中获取计数
【发布时间】:2020-08-25 23:19:54
【问题描述】:

如何在 ASP.NET Core 中运行原始查询以从表中返回行数?

目前,我正在这样做,返回的结果是-1。我认为返回结果是基于受影响的记录数。

 int numberOfRows = await
                    appDbContext.Database.ExecuteSqlInterpolatedAsync(
                        $"SELECT CODE FROM [samaster] WHERE CODE={productBrandCode} AND WAREHOUSE={warehouse} ");

任何关于如何将计数返回到 numberOfRows 变量的想法将不胜感激。

注意:上表不是模型,所以我需要运行原始查询。

谢谢

【问题讨论】:

  • 如果有帮助,请将答案标记为已接受,否则请发表评论。

标签: asp.net-core asp.net-core-mvc


【解决方案1】:

目前使用ExecuteSqlInterpolatedAsync时无法获取查询结果。这同样适用于任何其他 LINQ 语句。

但是,您可以使用底层 ADO.net Provider:

    public IList<IDictionary<string, dynamic>> SelectDynamic(string table)
    {
        using (var command = Database.GetDbConnection().CreateCommand())
        {
            command.CommandText = $"SELECT * FROM [{table}]";
            command.CommandType = CommandType.Text;

            Database.OpenConnection();

            using (var result = command.ExecuteReader())
            {
                var entities = new List<IDictionary<string, dynamic>>();

                while (result.Read())
                {
                    var dict = new Dictionary<string, dynamic>();

                    for (int i = 0; i < result.FieldCount; i++)
                    {
                        dict.Add(result.GetName(i), result.GetValue(i));
                    }

                    entities.Add(dict);
                }

                return entities;
            }
        }
    }

将此添加到您的 DbContext 类并调用它:

using (var context = new MyDbContext()) // Or get it with DI, depends on your application
{
     var count = context.SelectDynamic("samaster").Where(d => d["CODE"] == productBrandCode && d["WAREHOUSE"] == warehouse).Count();
}

但是请注意,如果您的表中有很多行,这是一项昂贵的操作! 仅获取相关结果的另一种方法是替换

command.CommandText = $"SELECT * FROM [{table}]";

与

command.CommandText = $"SELECT CODE FROM [samaster] WHERE CODE={productBrandCode} AND WAREHOUSE={warehouse}";

并将参数作为函数参数传递。

public IList<IDictionary<string, dynamic>> SelectDynamic(string productBrandCode, string warehouse)
    {...

如果用户输入以任何方式提交的所有参数,请确保对所有参数进行转义,以防止 SQL 注入攻击!

【讨论】:

  • 是的,我最终使用了命令语法。奇怪的是,没有任何内置功能可以做到这一点。
【解决方案2】:

有两种常见的方法:

一个。

int numberOfRows = await appDbContext.Database.ExecuteSqlInterpolatedAsync($"SELECT CODE FROM [samaster] WHERE CODE={productBrandCode} AND WAREHOUSE={warehouse} ").Count();

B.

int numberOfRows = await appDbContext.Database.ExecuteSqlInterpolatedAsync($"SELECT count(*) FROM [samaster] WHERE CODE={productBrandCode} AND WAREHOUSE={warehouse} ").First();

【讨论】:

  • 我认为您应该明确指出,只有在将字符串插值作为将查询参数传递给 ExecuteSqlInterpolatedAsync 的一部分直接完成时,此代码才能安全地防止 sql 注入。当您之前通过存储在单独的变量中来插入字符串时,此代码将易受攻击。
  • 上述查询sql注入问题不安全吗?
  • @XAMT 我没有任何名为 Cout() 或 First() 的方法
  • @Bikram;添加using System.Linq;
  • @XAMT 我不知道你是否测试过你的代码。但是使用 System.Linq 并不能解决我的 Count 方法
【解决方案3】:

由于没有人给我正确的答案。我最终使用以下内容。

public async Task<bool> IsAValidProduct(string productBrandCode)
        {
            int count = 0;
            await using DbCommand command = appDbContext.Database.GetDbConnection().CreateCommand();
            command.CommandText =
                "SELECT COUNT(CODE) FROM [samaster] WHERE CODE=@productBrandCode AND WAREHOUSE=@warehouse ";
            command.CommandType = CommandType.Text;
            command.Parameters.Add(new SqlParameter("@productBrandCode", SqlDbType.VarChar)
                {Value = productBrandCode});

            command.Parameters.Add(new SqlParameter("@warehouse", SqlDbType.VarChar)
                {Value = warehouse});
            await appDbContext.Database.OpenConnectionAsync();

            count = (int) await command.ExecuteScalarAsync();

            await appDbContext.Database.CloseConnectionAsync();
            return count == 1;
        }

【讨论】:

    猜你喜欢
    • 2016-06-11
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    • 2016-09-14
    • 2016-05-20
    • 1970-01-01
    • 2019-04-18
    • 2018-01-27
    相关资源
    最近更新 更多