2

I have a class inside my class library that has a method which uses a list with a SqlDataReader to cycle through all the records.

public List<myDetails> GetAddressDetails(int id)
{
    List<myDetails> mydetails = new List<myDetails>();
    myDetails details;

    try
    {
        using (SqlDataReader rdr = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                details = new myDetails((
                    reader.GetString(reader.GetOrdinal("FieldName")));

                mydetails.Add(details);
        }
        rdr.Close();
        return mydetails;
    }
}

I am trying to use a StringBuilder to build an HTML table, but having trouble figuring out how to loop through my list collection correctly. I tried a couple of different for loops but they were not giving the correct results.

    var item = clib.GetAddressDetails(Convert.ToInt32(Session["mysession"]));

        if (item != null)
        {      
            StringBuilder htmlStr = new StringBuilder("");
            htmlStr.Append("<center><h2 class='headings'>Addresses</h2>");
            htmlStr.Append("<table border='1' cellpadding='3'>");

foreach (var detail in item)
{
            htmlStr.Append("<tr>");
            htmlStr.Append("<td width='25px'>" + item.FieldName + "</td><tr>");
            htmlStr.Append("</tr>");
            htmlStr.Append("</table></center><br/>");
            divAddresses.InnerHtml = htmlStr.ToString();   
    }


        }

2 Answers 2

3

You need to use a loop. Either foreach or a simple for or while loop would work:

// initialize the string builder outside the loop!
StringBuilder htmlStr = new StringBuilder("");

// build out the header outside the loop..
htmlStr.Append("<center><h2 class='headings'>Addresses</h2>");
htmlStr.Append("<table border='1' cellpadding='3'>");

// retrieve the id from the session
int id = Convert.ToInt32(Session["mysession"]);

// then loop over the items returned
foreach(var item in clib.GetAddressDetails(id))
{
    if (item != null)
    {                                       
        htmlStr.Append("<tr>");
        htmlStr.Append("<td width='25px'>" + item.FieldName + "</td><tr>");
        htmlStr.Append("</tr>");
    }
}

// finish building your table outside the loop..
htmlStr.Append("</table></center><br/>");

// set the contents of the string builder as the inner HTML of the DIV element
divAddresses.InnerHtml = htmlStr.ToString(); 
Sign up to request clarification or add additional context in comments.

5 Comments

foreach (var item in clib.GetAddressDetails(Convert.ToInt32(Session["mysession"])).FirstOrDefault()) {
When i try this it says that it does not contain a public definiton for GetEnumerator
@Tim - I'm sorry, but why are you adding .FirstOrDefault() to the method call? That gives you a single item (first one) in the enumeration..
Without the firstordefault i was not able to access my list values like so item.name, item.address, item.state, item.city and so on sorry if I am doing that wrong I asked a question last week and was shown this method
@Tim - have you tried my example without the .FirstOrDefault() call? That is useful in a different scenario, not when you are iterating through all the items in the collection which is what you need in order to construct the table.
2

Your problem is this code:

foreach (var item in clib.GetAddressDetails(Convert.ToInt32(Session["mysession"])).FirstOrDefault()) 
{
    // Do stuff
}

The FirstOrDefault() portion takes the list you generated and selects the first one in the list or returns null.

Instead do this:

var item = clib.GetAddressDetails(Convert.ToInt32(Session["mysession"]));

Now you can use a foreach loop to build a table row (<tr>) for each item in the list, like this:

foreach(var detail in item)
{
    htmlStr.Append("<tr>");
    htmlStr.Append("<td width='25px'>" + detail.FieldName + "</td><tr>");
    htmlStr.Append("</tr>");
}

Note: You should consider changing the name of your variable for the returned List<myDetails> to something more intuitive, like listOfDetails instead of item.

So the entire code should look like this:

public List<myDetails> GetAddressDetails(int id)
{
    List<myDetails> mydetails = new List<myDetails>();
    myDetails details;

    try
    {
        using (SqlDataReader rdr = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                details = new myDetails(
                              (reader.GetString(reader.GetOrdinal("FieldName")));
                mydetails.Add(details);
        }
        rdr.Close();
        return mydetails;
    }
}

var item = clib.GetAddressDetails(int id);

if (item != null)
{
    StringBuilder htmlStr = new StringBuilder("");
    htmlStr.Append("<center><h2 class='headings'>Addresses</h2>");

    htmlStr.Append("<table border='1' cellpadding='3'>");

    foreach(var detail in item)
    {
        htmlStr.Append("<tr>");
        htmlStr.Append("<td width='25px'>" + detail.FieldName + "</td><tr>");
        htmlStr.Append("</tr>");
    }

    htmlStr.Append("</table></center><br/>");
    divAddresses.InnerHtml = htmlStr.ToString(); 
}

7 Comments

When i try this it says that it does not contain a public definiton for GetEnumerator
foreach (var item in clib.GetAddressDetails(Convert.ToInt32(Session["mysession"])).FirstOrDefault()) { –
Ah, you left that little bit of information out, FirstOrDefault() is returning a single myDetails object or null, thus there is nothing to loop through. Why are you building a list to only pick the first one in the list?
That was not my intentions it is more of a lack of knowledge I am learning how to use list collections in a class library and still getting the hang of things i guess. But without firstordefault when I type item.fieldname the fieldname does not exist how else would I do this?
@Tim - you should try the samples provided and examine the state of variables at runtime with the debugger. That way it will become obvious that you can in fact access the members of the details object because the foreach block iterates over the collection mapping the item variable to each element in the collection, one at a time.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.