【问题标题】:Query returns results 5 times查询返回结果 5 次
【发布时间】:2010-11-13 11:31:00
【问题描述】:

我有一个奇怪的问题。我在 C#/ASP.NET 中的查询返回结果 5 次。我尝试了刹车点,但我找不到错误。我有 2 个相关的表。一个表在 PAGE_LOAD 上加载,当用户单击一个单元格时,它会显示与该单元格相关的另一个表中的内容。很简单。

    //PAGE LOAD
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        OleDbConnection myConnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + dbpath + "/secure_user/data/data.mdb");
        OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT Project,Manager,Customer,Deadline FROM projects WHERE Username='" + uname + "'", myConnection);
        DataTable table = new DataTable();
        adapter.Fill(table);
        adapter.Dispose();
        GridView1.DataSource = table;
        GridView1.DataBind();
    }
}

它将项目表加载到 GridView。现在,当我单击某个项目时,它会显示有关该项目的更多信息:

protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
    GridViewRow row = GridView1.SelectedRow;
    Label1.Text = row.Cells[1].Text;
    OleDbConnection myConnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + dbpath + "/secure_user/data/data.mdb");
    OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT tasks.Task,tasks.Priority,tasks.Done,taska.Hours FROM projects,tasks WHERE tasks.Username='" + uname + "' AND tasks.Project='" + Label1.Text + "'", myConnection);
    DataTable table = new DataTable();
    adapter.Fill(table);
    adapter.Dispose();
    GridView2.DataSource = table;
    GridView2.DataBind();
    GridView2.Visible = true;
}

它显示没有错误,但无论我从 GridView1 中选择什么项目,它都会显示 5 次,它总是连续显示 GridView2(第二个表)内容 5 次。可能是什么问题?

【问题讨论】:

  • 第二个 SELECT 语句 (taska) 中似乎有错字。
  • 顺便说一句,这种查询很容易成为脚本攻击的目标;请不要使用未经验证的页面可编辑字段内容。
  • 有人需要阅读关于小圆桌的文章...

标签: c# asp.net sql gridview


【解决方案1】:

您的查询似乎有问题。尝试使用 INNER JOIN 而不是 ,。

而不是这个:

SELECT tasks.Task, tasks.Priority, tasks.Done, tasks.Hours
FROM projects, tasks
WHERE tasks.Username='" + uname + "' AND tasks.Project='" + Label1.Text + "'

试试这个:

SELECT tasks.Task, tasks.Priority, tasks.Done, tasks.Hours
FROM projects INNER JOIN tasks ON projects.ID = tasks.ProjectID --> may not be correct depends on your table structure
WHERE tasks.Username='" + uname + "' AND tasks.Project='" + Label1.Text + "'

另一件事:构建这样的 SQL 查询很容易出现SQL Injection attack

【讨论】:

  • 哇,完美!非常感谢!我希望我能投票给你,但我又错过了 14 次。谢谢!我会考虑 SQL 注入预防。谢谢大家。
【解决方案2】:

您正在projects 表和tasks 表之间进行交叉连接,因此您将每个项目与您选择的项目的每个任务连接起来。由于您有五个项目,因此您每项任务都会获得五次。

使用连接指定projects 表和tasks 表之间的关系:

OleDbDataAdapter adapter = new OleDbDataAdapter(
   "SELECT tasks.Task,tasks.Priority,tasks.Done,taska.Hours "+
   "FROM projects "+
   "INNER JOIN tasks ON tasks.Project = projects.Project "+
   "WHERE projects.Username='" + uname + "' AND projects.Project='" + Label1.Text + "'", myConnection);

注意:
请注意,我使用了projects 表中的用户名字段,而不是tasks 表。要么你在表中有冗余,要么字段意味着不同的东西。如果其他用户可以将任务添加到您的项目中,那么如果您只想查看自己添加的任务,您也需要 tasks.Username 字段的条件。

【讨论】:

  • 查看我添加的注释,与 Adrian 建议的查询存在一些差异......
【解决方案3】:

可能是这个查询返回了多条记录;你能列出使用过的表中的主键吗

【讨论】:

    【解决方案4】:

    在您的第二个查询中,您有一个连接,各种各样。您永远不会从项目表中返回 SELECT 中的任何内容,但它在查询中被引用。我猜你有 5 个项目。

    此外,您正在向查询中注入数据。这很糟糕,因为攻击者很容易对您的代码和数据库发起 SQL 注入攻击,尤其是当您直接使用来自控件的数据时。您应该考虑至少使用参数化查询。

    【讨论】:

    • 我明白这一点。我将阅读有关 SQL 注入的更多信息。谢谢。
    【解决方案5】:

    您尝试在查询中添加 DISTINCT 子句。因为如果未显示,则您的查询是笛卡尔积。

    OleDbDataAdapter 适配器 = new OleDbDataAdapter("SELECT DISTINCT tasks.Task,tasks.Priority,tasks.Done,taska.Hours FROM projects,tasks WHERE tasks.Username='" + uname + "' AND tasks.Project='" + Label1.Text + "'", myConnection);

    【讨论】:

    • 我已经解决了这个问题,但我会考虑到这一点。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-08-30
    • 2013-10-01
    • 2021-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多