查询只给出一个结果

时间:2015-04-18 16:24:26

标签: c# sql

我的查询只给出一个结果,即一个url的一个单词应该为dt中的每个条目运行。这里的dt是 DataTable 并且包含很多行, url_given 是一个字符串。 temp 是包含要匹配的字词的表格。任何人都可以告诉我我的查询有什么问题。 wordcount是表的名称。 url_String,word和count是列。

  

查询的目的是获取与给定网址匹配的网址   列表中的单词 temp

 foreach (DataRow row in dt.Rows)
 {

         // read item
         url_given = row["url_String"].ToString();

         String qrystring = "select url_String,word,count from wordcount where url_String='" + url_given + "' and word in (select * from temp) ";
         dt1 = db.searchandorder(qrystring);
     // searchandorder is a call to a function that establishes the db connections and passes the query to the data adapter.

 }

这是我的搜索功能

public DataTable searchandorder (String sql)
{
    conn.Open();

    SqlDataAdapter da = new SqlDataAdapter(sql, conn);
    DataSet ds = new DataSet();
    DataTable dt = new DataTable();
    da.Fill( dt);


    conn.Close();
    Console.Write("table coloumns" + dt.Columns.ToString());

    return dt;
}

1 个答案:

答案 0 :(得分:3)

你的问题来自你每次循环覆盖dt1的事实。你需要合并结果而不是替换它们,但我不能说如何在没有看到db.searchandorder的情况下这样做。

你也有一个非常危险的SQL注入攻击。如果url_given'; drop table wordcount; --那么程序将在服务器上执行的查询是什么?您需要将parameters与数据适配器一起使用。

编辑:那么,既然你已经展示了代码,那么就是你如何修复它。您每次通过时都不会创建一个新的DataTable,而是在循环之外创建一个并且每次都传入同一个表。 TableAdapter默认填写之前不会清除表格。

private YourFunction(DataTable dt)
{
    DataTable dt1 = new DataTable();

    foreach (DataRow row in dt.Rows)
     {
         // read item
         url_given = row["url_String"].ToString();

         String qrystring = "select url_String,word,count from wordcount where url_String='" + url_given + "' and word in (select * from temp) ";
         db.searchandorder(qrystring, dt1);
         // searchandorder is a call to a function that establishes the db connections and passes the query to the data adapter.
     }

    DoSomthingWithResults(dt1);
}

public void searchandorder (String sql, DataTable dt)
{
    conn.Open();

    SqlDataAdapter da = new SqlDataAdapter(sql, conn);
    da.Fill( dt);


    conn.Close();
    Console.Write("table coloumns" + dt.Columns.ToString());

    return dt;
}

现在,这是使您的计划有效的最低要求。你正在做很多其他不好的做法。

  • 不要重复使用连接:您的conn对象应该在searchandorder内创建,并且在using语句中。不要担心连接太多",.NET会使用connection pooling并重复使用旧连接。

  • 使用using语句:任何实现IDisposable的内容都应该在using语句中(除非该项目被返回)

  • 遵循命名标准:后面有set of standards个C#代码,您的班级searcandhorder应命名为SerchAndOrder

  • 使用参数:您容易受到数据适配器的SQL injection attack使用参数的攻击。它不仅提高了安全性,还允许SQL服务器缓存查询执行计划,从而加快程序运行。

以下是应用了这些修补程序的程序版本。

private YourFunction(DataTable dt)
{
    DataTable dt1 = new DataTable();

    foreach (DataRow row in dt.Rows)
     {
         // read item
         url_given = row["url_String"].ToString();
         var parameter = new SqlParameter("@urlGiven", SqlDbType.VarChar, url_given.Length);
         parameter.Value = url_given;

         String qrystring = "select url_String,word,count from wordcount where url_String=@urlGiven and word in (select * from temp) ";
         db.searchandorder(qrystring, dt1, parameter);
         // searchandorder is a call to a function that establishes the db connections and passes the query to the data adapter.
     }

    DoSomthingWithResults(dt1);
}

public void SearchAndOrder (String sql, DataTable dt, params SqlParameter[] parameters)
{
    using(var conn = new SqlConnection(_connectionString))
    using(var da = new SqlDataAdapter(sql, conn))
    {
        da.SelectCommand.Parameters.AddRange(parameters);
        conn.Open();
        da.Fill(dt);
    }

    Console.Write("table coloumns" + dt.Columns.ToString());

    return dt;
}