首页 > 解决方案 > SqlDataAdapter.SelectCommand 没有返回正确的结果

问题描述

我只是面临我的代码问题。

我想使用 SqlDataAdapter SelectCommand 属性从数据库中选择一些数据。

我的代码如下所示:

static SqlConnection sqlConnection;
static SqlDataAdapter daDBData = new SqlDataAdapter();
static SqlCommand command = new SqlCommand();
static DataSet dsDBData = new DataSet("DBData");
static DataTable tblDBData;
static DataRow drCurrent;

public static DataTable dbDataGet(string tabname, string where)
{
    sqlConnection = dbConnect();    //sqlConnection setup working fine, defined in another method
    string helper = "SELECT * FROM " + tabname + where; 
    command = new SqlCommand(helper, sqlConnection);
    daDBData.SelectCommand = command;

    daDBData.MissingSchemaAction = MissingSchemaAction.AddWithKey;
    daDBData.Fill(dsDBData, tabname);

    tblDBData = dsDBData.Tables[tabname];
    return tblDBData;
}

我的问题是,在tblDBData我的数据库表的所有现有行中都将返回。我在这里想念什么?

标签: c#datasetsqlcommandsqldataadapter

解决方案


就代码块而言,可以公平地说它需要大量工作。几乎每一行都有一些可以改进的地方,但它所体现的整个概念是相当令人反感的,因为它本质上是一个巨大的安全风险。这是一个稍微改进的版本:

//Don't need any of those static variables. Stop making everything static..
//In a properly structured C# program almost NOTHING should be declared as static

        //Method names in C# use PascalCase convention, not camelCase
        public DataTable DbDataGet(string tableName, string whereClause)
        {

            //this could be a massive security risk if there is any way at all that the 
            //user can influence the contents of the whereClause. DON'T DO IT if they can
            SqlDataAdapter da = new SqlDataAdapter(
              $"SELECT * FROM {tableName} WHERE {whereClause}",
              GetConnectionString() //in this simplistic context, get a string, not a SqlConnection, then you don't handle disposal
            );

            DataTable dt = new DataTable();

            da.Fill(dt);

            return dt;
        }

是的; 您编写的所有代码归结为只有 4 行。这仍然是一个大问题,你只是在扔一个带有 where 子句的字符串。使用这种方法摆脱这种情况的唯一方法是开始将您的 where 字符串分解为一组谓词类,在列和运算符级别保护 sql 注入,并将值添加到 SqlParameterCollection - 它本质上是滚动您自己的数据访问图书馆,鉴于许多人已经这样做了(包括微软),不值得费心

考虑通过根本不以这种方式访问​​数据来摆脱这个可怕的兔子洞。把它全部扔进垃圾桶,改用Dapper。从你现在的情况来看,这并不是一个巨大的学习曲线,并且将以更安全、更安全、更易于使用的方式完成所有工作


作为关于 WHERE 子句的注释,您在使用的评论中说:

WHERE DATEDIFF(day, sale_date, GetDate()) >= 365 AND available=1

也不要这样做。在这里,您对表中的数据条目执行函数操作。如果您的表中有一百万个日期,则该函数将需要调用一百万次。它很慢,使用大量资源并削弱了索引的使用。这是完全没有必要的。您正在寻找一年前售出的所有产品?计算一年前的某个日期,并使用SALE_DATEfrom th 故事与它相比没有任何改变:

-- in your sql
WHERE sale_date < @someDate and available = 1

//in your c#
mySqlCommand.Parameters.AddWithValue("@someDate", DateTime.UtcNow.AddYears(-1));

看到不同?在这里,c# 计算一次日期,并将其作为常量值参数提供给查询。在包含一百万个日期的表中,只执行一个简单的比较。我们不计算多少天前有一百万个不同的日期,然后只选择那些差异 > 365


推荐阅读