-2

I am trying to display percentage based on the rank of each record returned in search. I want it to loop through each item but it only loops through the first item as many times as I have items. For instance if it found 4 results it would display the rank of the first one on all 4 results.

Any suggestions to get it to display each rank separately and convert it to percentage?

private void BindRpt()
{
    if (string.IsNullOrEmpty(txtSearch.Text)) return;
    SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["DB"].ConnectionString);
    cn.Open();
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = cn;
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    cmd.CommandText = "select Distinct Rank, SUBSTRING(ColumnA, 1, 500) AS ColumnA, ColumnB, ColumnC, ColumnD, ColumnE from FREETEXTTABLE (TABLE , ColumnA, '" + Search.Text + "'  ) S, TABLE C WHERE c.ID = S.[KEY] order by Rank Desc";

    DataTable dt = new DataTable();
    adapter.SelectCommand = cmd;
    adapter.Fill(dt);

    PagedDataSource pgitems = new PagedDataSource();
    pgitems.DataSource = dt.DefaultView;
    pgitems.AllowPaging = true;

    pgitems.PageSize = 3;
    pgitems.CurrentPageIndex = PageNumber;
    if (pgitems.Count > 1)
    {                
        rptPaging.Visible = true;
        ArrayList pages = new ArrayList();
        for (int i = 0; i <= pgitems.PageCount - 1; i++)
        {
            pages.Add((i + 1).ToString());
        }
        rptPaging.DataSource = pages;
        rptPaging.DataBind();

        lblSentence.Visible = true;
        lblSearchWord.Visible = true;
        lblSearchWord.Text = txtSearch.Text;
    }
    else 
    {
        rptPaging.Visible = false;

        lblSentence.Visible = true;
        lblSentence.Text = "Results were found for";

        lblSearchWord.Visible = true;
        lblSearchWord.Text = txtSearch.Text;
    }
    rptResults.DataSource = pgitems;
    rptResults.DataBind();
    cn.Close();
}

protected void rptResults_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["HTAA"].ConnectionString);
    cn.Open();
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = cn;
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    cmd.CommandText = "select Distinct Rank, SUBSTRING(ColumnA, 1, 500) AS ColumnA, ColumnB, ColumnC, ColumnD, ColumnE from FREETEXTTABLE (TABLE , ColumnA, '" + Search.Text + "'  ) S, TABLE C WHERE c.ID = S.[KEY] order by Rank Desc";


    int number = Page.Items.Count;
    SqlDataReader dr = cmd.ExecuteReader();
    if(dr.Read())
    {
        int firstrank = dr.GetInt32(0);
        while (dr.Read())
        {
            int rank = dr.GetInt32(0);
            int percentage = (rank / firstrank) * 100;
            Label lblpre = (Label)e.Item.FindControl("lblRank");
            lblpre.Text = percentage.ToString();
        }
    }
    dr.Close();
    cn.Close();
}
Humayun Shabbir
  • 2,961
  • 4
  • 20
  • 33
Victor_Tlepshev
  • 478
  • 6
  • 19
  • 6
    `int percentage = (rank / rank) * 100;` Will always result in a value of 100, no matter what `rank` is. – p e p Aug 01 '14 at 18:13
  • Your code has a number of issues. In addition to the logic error pointed out above, and the looping issue pointed out in the answers, it's vulnerable to SQL injection. You're not properly wrapping things in `using` statements. You may want to do a bit more research on the basics. – David Crowell Aug 01 '14 at 18:19
  • What do you expect the data to look like? If you have four records, they're ranked 1..4, right? What should your result look like? – tbddeveloper Aug 01 '14 at 18:21
  • I changed the code, it seems like it is doing it but it displays 0 – Victor_Tlepshev Aug 01 '14 at 18:22

4 Answers4

1

After a chat, I have a better handle on things. A way to do this;

Create a private field on your code behind file.

private int topRanked = 0; 

In your Bind method()

private void Bind() 
 { 
 ... 
 DataTable dt = new DataTable(); 
 adapter.SelectCommand = cmd; 
 adapter.Fill(dt); 

 topRanked = (int)dt.Rows[0]["Rank"];

Now, make your OnItemDataBound method;

protected void OnItemDataBound(object sender, RepeaterItemEventArgs e) 
 { 
 var dataItem = e.Item.DataItem as DataRowView; 
 int rank = (int) dataItem["Rank"]; 

 var percentage = ((double)topRanked / rank) * 100; 

 Label label = (Label)e.Item.FindControl("labelRank"); 

 label.Text = percentage.ToString(); 
 }

as mentioned. I don't believe it's the best answer, but it is an answer. I'm sure a stored procedure, or even a better sql method could probably calculate this and not leave you making calculations in code.

tbddeveloper
  • 2,407
  • 1
  • 23
  • 39
0

Can you try with while(dr.Read()) instead of "if"?

ssug89
  • 249
  • 2
  • 8
0

You will want to loop over the result set

while (dr.Read())
{
   int rank = dr.GetInt32(0);
   int percentage = (rank / rank) * 100;
   Label lblpre = (Label)e.Item.FindControl("lblRank");
   lblpre.Text = rank.ToString();

}
vesuvious
  • 2,753
  • 4
  • 26
  • 39
0

"but it only loops through the first item" - because you have a for and checks for i <= 0

for (int i = 0; i <= 0; i++) 
{
   ....
}

You just don't need this for statement but rather use

if (dr != null)
   using (dr)
   {
         while (dr.Read())
         {
          ..
         }
   }

It's always better to use using when dealing with db connection objects so the resources used by these objects are properly disposed after it's been used.

Dennis R
  • 3,195
  • 1
  • 19
  • 24