CodeSmith Community
Your Code. Your Way. Faster!

Displaying Data

Latest post 12-16-2007 5:38 PM by Polar. 14 replies.
  • 12-05-2007 8:31 AM

    • brcvogt
    • Top 75 Contributor
    • Joined on 02-21-2007
    • South Africa
    • Posts 61
    • Points 1,445

    Displaying Data

    Hi,

    I need to display my categories on the home plus three or four of each category's sub categories.  To get an idea of what I am looking for please go to http://shopping.aol.com, look how they did it.  This is what I need.

    My category table has a category name and a parent category ID that references a category ID.

    I need advice on how to do this.  Is there a control already built that does something like this?  If not, are there methods that bring back category records with their child categories.  Please can someone advise me on what to look out for or what to use??

    Thanks
    Brendan

    Wink

    • Post Points: 35
  • 12-05-2007 12:36 PM In reply to

    • Polar
    • Top 100 Contributor
    • Joined on 09-04-2007
    • Posts 49
    • Points 895

    Re: Displaying Data

    If you created a self-join on the category table in yout db (ParentCategoryID references CategoryID) then you can simply deepload the subcategories.

    CategoryService service = new CategoryService();
    TList<Category> rootCategories = service.GetAll();
    service.DeepLoad(rootCategories, false, DeepLoadType.IncludeChildren, typeof(TList<Category>));

    Now each Category in rootCategories has a child TList with its subcategories.

    One think I would like to know is whether it is necessary to call service.GetAll() before deeploading the list, or will DeepLoad fill the rootCategories if it is empty?

     

    Filed under:
    • Post Points: 35
  • 12-06-2007 9:56 AM In reply to

    • vbandrade
    • Top 25 Contributor
    • Joined on 09-27-2007
    • Brasil
    • Posts 213
    • Points 5,305

    Re: Displaying Data

    CategoryService service = new CategoryService();

    TList<Category> rootCategories = service.GetParentCategories(); //You dont need to load all categories, load just the ones that have parentId null. make a custom procedure

    service.DeepLoad(rootCategories, false, DeepLoadType.IncludeChildren, typeof(TList<Category>));

    That´s the only change I would make.

    • Post Points: 65
  • 12-06-2007 4:43 PM In reply to

    • Polar
    • Top 100 Contributor
    • Joined on 09-04-2007
    • Posts 49
    • Points 895

    Re: Displaying Data

    Yea, obviously no need to load the whole list. I don't know why I missed that.

    I also found out that DeepLoad will not load the TList that you are deeploading. Meaning rootCategories needs to be instantiated before it can be used in DeepLoad. 

    • Post Points: 5
  • 12-08-2007 2:45 AM In reply to

    • brcvogt
    • Top 75 Contributor
    • Joined on 02-21-2007
    • South Africa
    • Posts 61
    • Points 1,445

    Re: Displaying Data

    Hi,

    GetParentCategories() is a method that I need to create??  How would I loop through it to get the children categories for each??

    Thanks
    Brendan

    • Post Points: 35
  • 12-08-2007 2:54 PM In reply to

    • Polar
    • Top 100 Contributor
    • Joined on 09-04-2007
    • Posts 49
    • Points 895

    Re: Displaying Data

    You would have to create a custom stored procedure to return only the categories that don't have a parent id (hence root/parent categories).  This custom stored procedure would be automatically generated into the entity service provided you configured the template correctly. I wouldn't recommend this for such a simple query.  Your other option is to use a <Entity>Query object with the Find method of the service like this:

    TList<Category> categories;
    CategoryQuery query = new CategoryQuery();
    CategoryService service = new CategoryService();

    query.AppendIsNull(CategoryColumn.CategoryParentID);
    categories = service.Find(query.GetParameters(), "CategoryName"); // Second param is the sort
    service.DeelLoad(categories, false, DeepLoadType.IncludeChildren, typeof(TList<Categories>));

    Now you have a list of root categories where each category has a child collection of the child categories called "CategoryCollection"  
    You can loop through them like this:

    foreach(Category parent in categories)
    {
        Console.WriteLine(parent.CategoryName);

        foreach(Category child in parent.CategoryCollection)
        {
            Console.WriteLine("\t" + child.CategoryName);
        }
    }
    • Post Points: 60
  • 12-09-2007 10:42 AM In reply to

    • brcvogt
    • Top 75 Contributor
    • Joined on 02-21-2007
    • South Africa
    • Posts 61
    • Points 1,445

    Re: Displaying Data

    Thanks for this, but is there anyways that I can maybe pass a parameter through because some parent categories (and child categories) might be marked as inactive.

    • Post Points: 5
  • 12-09-2007 11:38 AM In reply to

    • brcvogt
    • Top 75 Contributor
    • Joined on 02-21-2007
    • South Africa
    • Posts 61
    • Points 1,445

    Re: Displaying Data

    I also need to display parent categories (as well as child categories) that have the Visible column set to true.  So I tried this and it gives me an error:

    query.AppendIsNull(CategoryColumn.ParentCategoryId);
    query.AppendEquals(CategoryColumn.Visible, "1");

    Why won't this work? 

    • Post Points: 5
  • 12-09-2007 11:43 AM In reply to

    • brcvogt
    • Top 75 Contributor
    • Joined on 02-21-2007
    • South Africa
    • Posts 61
    • Points 1,445

    Re: Displaying Data

    query.AppendIsNull(CategoryColumn.ParentCategoryId);
    query.AppendEquals(CategoryColumn.Visible, "True");

    It works, but did I do it right?

    • Post Points: 35
  • 12-09-2007 4:05 PM In reply to

    • Polar
    • Top 100 Contributor
    • Joined on 09-04-2007
    • Posts 49
    • Points 895

    Re: Displaying Data

     Are you using SQL Server? As far as I know 1/0 and True/False are analogous and treated as equal in SQL Server, so your previous code should work.

    The query that you created will return the parent categories that have visible set to.  Unfortunatelly, you cannot specify a where clause when deeploading the child categories so you cannot specify that you only want to return the visible ones.  The simplest way to handle this would be to filter the child categories after you have deeploaded them, but this way you deepload ALL of the child categories for each parent regardless of their visible status.  This is where you are as programmer/developer need to decide what is the best course of  action.  

    Things you have to consider are:

    • The number of child categories that will need to be loaded for each parent.
    • What is the ratio between the visible and non visible child categories. Does it make sense to load 100 child categories if only 5 of them are visible?

    While load time may not be something you are concered with (you may be loading only a couple categories),  your code still should be scalable and logical. With that said if most of your child categories will be visible then I would just filter the list after deeploading like this:

    rootCategories.ForEach(delegate(Category root)
    {
        root.CategoryCollection.ApplyFilter(delegate(Category child)
        {
            child.Visible == true;
        });
    });

    I used a delegate for the ForEach loop as it is faster than the foreach loop.  The ApplyFilter methods also takes a delegate where you can add any code to help you flter the list.  Also, I would recommend that you don't use the word "Visible" as a column name because if you ever decide to create User Controls for your entities then you're going to have a problem since the UC will have a Visible property.  I would use a world like "Active" instead.

    • Post Points: 60
  • 12-15-2007 7:51 AM In reply to

    • brcvogt
    • Top 75 Contributor
    • Joined on 02-21-2007
    • South Africa
    • Posts 61
    • Points 1,445

    Re: Displaying Data

    Sorry for getting back now.  I'm not understanding your code at all.  Please look at my piece of code and see if you can tell me, or modify my code to fit yours in.  Also, the child categories, I need to sort them according to the value in the Sequence field.

    TList<Category> categories;
    CategoryQuery query = new CategoryQuery();
    CategoryService service = new CategoryService();

    // Append query parameters
    query.AppendIsNull(CategoryColumn.ParentCategoryId);
    query.AppendEquals(CategoryColumn.Active, "True");
    // Sort by sequence ascending
    categories = service.Find(query.GetParameters(), "Sequence ASC"); // Second param is the sort
    // Deep load child categories
    service.DeepLoad(categories, false, DeepLoadType.IncludeChildren, typeof(TList<Category>));

    foreach (SAMarketplaceTest.Entities.Category parent in categories)
    {
        LiteralControl litCategory = new LiteralControl("<h2>" + parent.CagtegoryName + "</h2>");
        pnlCategoriesLeft.Controls.Add(litCategory);
        // Child categories
        foreach (Category child in parent.CategoryCollection)
        {
            Response.Write("\t" + child.CagtegoryName);
        }
    }

     

    Please help.

    Regards,
    Brendan

    • Post Points: 5
  • 12-15-2007 11:32 AM In reply to

    • brcvogt
    • Top 75 Contributor
    • Joined on 02-21-2007
    • South Africa
    • Posts 61
    • Points 1,445

    Re: Displaying Data

    Hi,

    This section from your code above does work:

    root.CategoryCollection.ApplyFilter(delegate(Category child) { } );

    Error is:

    Error    1    The best overloaded method match for 'SAMarketplaceTest.Entities.ListBase<SAMarketplaceTest.Entities.Category>.ApplyFilter(System.Predicate<SAMarketplaceTest.Entities.Category>)' has some invalid arguments

    Error    2    Argument '1': cannot convert from 'anonymous method' to 'System.Predicate<SAMarketplaceTest.Entities.Category>'

    PLease advise as what to do.

    Thanks 

    • Post Points: 35
  • 12-15-2007 5:11 PM In reply to

    • Polar
    • Top 100 Contributor
    • Joined on 09-04-2007
    • Posts 49
    • Points 895

    Re: Displaying Data

    That error 2 message is incorrect and Microsoft is aware of it. The real error message should be "Not all code paths return a value".  I missed the return keyword before child.Visible == true, because the ApplyFilter accepts a predicate that returns a boolean. So that line should be:   return child.Visible == true;

    When you say you don't understand are you talking about the delegate thing?   Check out http://msdn2.microsoft.com/en-us/library/ms173171(VS.80).aspx

    rootCategories.ForEach(delegate(Category root) {}); is the same as foreach(Category root in rootCategories) {}     (performance is almost identical, depends what you are doing)

    The ApplyFilter method accepts a Predicate and there are two ways you can code it.  One way is creating an anonymous method how I did above, or you can actually create a method if you might use it somewhere else.

    root.CategoryCollection.ApplyFilter(IsCategoryVisible);

    private bool IsCategoryVisible(Category item) 
    {
        return item.Visible;
    }

    Another way to filter the TList is using a filter string:

    root.Categories.Filter = "Visible = true";
    root.Categories.ApplyFilter();

    While the last method looks very simple its not type safe.  It really pays of using Predictes when dealing with more complex logic.
     

    • Post Points: 35
  • 12-16-2007 3:49 AM In reply to

    • brcvogt
    • Top 75 Contributor
    • Joined on 02-21-2007
    • South Africa
    • Posts 61
    • Points 1,445

    Re: Displaying Data

    Thanks Polar!!

    I'm almost done with this post, I just need 3 more questions answered:

    1. Can I maybe apply another filter?
    2. How do I sort the child categories according to their Sequence field which is numbered 1, 2, 3, etc.?
    3. How do I print the child categories?

    I have been checking out the forums but could find nothing so I need you please to help me.  How would you have done this whole situation?

    I changed the code to look like this:

    categories.ForEach(delegate(Category root)
    {
         LiteralControl litCategory = new LiteralControl("<h2>" + root.CagtegoryName + "</h2>");
         pnlCategoriesLeft.Controls.Add(litCategory);
         // Child categories
         root.CategoryCollection.ApplyFilter(delegate(Category child)
         {
              return child.Active = true;
         });
    });

    Go to www.samarketplace.co.za so that you can see how I need the categories to be displayed.

    Thanks for all the help so far.

    Brendan
    (South Africa)

    • Post Points: 35
  • 12-16-2007 5:38 PM In reply to

    • Polar
    • Top 100 Contributor
    • Joined on 09-04-2007
    • Posts 49
    • Points 895

    Re: Displaying Data

    Make sure you have return child.Active == true or just return child.Active
    You can add more logic like:  return child.Active && child.County == "South Africa"
    The code in inside ApplyFilter will be run for each category item in the collection so you can put any code you wish and return True or False, where True means to include that item in the filtered list.

    You can filter the list with:
    root.CategoryCollection.Sort("Sequence ASC");
    Do that after applying the filter.

    If you want to only display the first 4 sub categories you might want to add child.Sequence < 5 to the ApplyFilter.
    Then you can use the CategoryCollection as a DataSource for a Repeater. To put the & symbol instead of the comma before the last item I guess you have to handle the Repearter Item event or something, where you check the datasource count.
    I'm a bit rusty with asp.net programming.
    • Post Points: 5
Page 1 of 1 (15 items) | RSS
Copyright © 2008 CodeSmith Tools, LLC
Powered by Community Server (Commercial Edition), by Telligent Systems