0

I've got an action which loads an array of strings which were checked by thier appropriate checkboxes on the page:

        public ActionResult Test1(string[] checked_strings)

I would like to use this strings which are equal on their name to the entities which i want to create a groupby statement dynamically.

Which will go on something like this:

            bool bChecked = Request.Form["checked_strings"].Contains("true");
            cmpqry =   from x in checked_strings
                       from y in typeof(Company).GetProperties()
                       where y.Name == x.ToString()
     // Create the groupby statement for the properties matched with the strings //

Any idea how to pull this over?

cmpqry holds the IEnumarable list(later returned to view) of the model's class.

3
  • Dynamic linq may be your answer, stackoverflow.com/questions/2448611/… Commented Feb 26, 2013 at 9:48
  • Already tried that and I can't convert it back to the EF model and list it properly to the view. If you think it's possible i'd like an example.. Thanks. Commented Feb 26, 2013 at 10:07
  • Couldn't manage to use the "GroupBy" of dynamic linq, it throws exeption as from this example : var groups = Model.GroupBy("SomeColumn, SomeOtherColumn") even after i've added the library file DynamicLibrary.cs - Please help!! Commented Feb 26, 2013 at 14:28

2 Answers 2

2

Here's the code sample that works - you should be able to supply the fields you want to group on in the order you want them to be grouped:

public class Company
{
    public int CompanyID { get; set; }
    public string CompanyName { get; set; }
    public string SubBranchName { get; set; }
    public string ProductName { get; set; }
}

public static class MyEnumerableExtensions
{
    /// <summary>
    /// Applies grouping to the collection of elements using the selectors specified
    /// </summary>
    /// <typeparam name="TElement">Type of the element</typeparam>
    /// <param name="elements">Elements to be grouped</param>
    /// <param name="groupSelectors">Selectors, or properties to be grouped on</param>
    /// <returns></returns>
    public static IEnumerable<GroupResult> GroupByMany<TElement>(
        this IEnumerable<TElement> elements,
        params Func<TElement, object>[] groupSelectors)
    {
        if (groupSelectors.Length > 0)
        {
            var selector = groupSelectors.First();

            //reduce the list recursively until zero
            var nextSelectors = groupSelectors.Skip(1).ToArray();
            return
                elements.GroupBy(selector).Select(
                    g => new GroupResult
                    {
                        Key = g.Key,
                        Items = g,
                        SubGroups = g.GroupByMany(nextSelectors)
                    });
        }
        return null;
    }

    public class GroupResult
    {
        public object Key { get; set; }
        public IEnumerable Items { get; set; }
        public IEnumerable<GroupResult> SubGroups { get; set; }
    }
}



//Your usage of the GroupByMany
IEnumerable<Company> list = new List<Company>
 {new Company{CompanyID = 1, CompanyName = "Company1", ProductName = "Product1", SubBranchName = "SB1"},
 new Company{CompanyID = 2, CompanyName = "Company1", ProductName = "Product2", SubBranchName = "SB2"},
 new Company{CompanyID = 3, CompanyName = "Company1", ProductName = "Product3", SubBranchName = "SB1"},
 new Company{CompanyID = 4, CompanyName = "Company2", ProductName = "Product4", SubBranchName = "SB2"},
 new Company{CompanyID = 5, CompanyName = "Company2", ProductName = "Product1", SubBranchName = "SB2"},
 new Company{CompanyID = 6, CompanyName = "Company2", ProductName = "Product2", SubBranchName = "SB1"},
 new Company{CompanyID = 7, CompanyName = "Company2", ProductName = "Product3", SubBranchName = "SB2"},
 new Company{CompanyID = 8, CompanyName = "Company3", ProductName = "Product4", SubBranchName = "SB2"},
 new Company{CompanyID = 9, CompanyName = "Company3", ProductName = "Product3", SubBranchName = "SB1"},
 new Company{CompanyID = 10, CompanyName = "Company3", ProductName = "Product2", SubBranchName = "SB2"},
 };

    var groupedByProductNameThenSubBranchName = list.GroupByMany(p => p.ProductName, p => p.SubBranchName);

    foreach (var groupResult in groupedByProductNameThenSubBranchName)
    {
        foreach (var result in groupResult.SubGroups)
        {
            foreach (var groupResult1 in result.Items)
            {
                Company company = groupResult1 as Company;
                Debug.Print(String.Format("ProductName: {0}, SubBranchName: {1}", company.ProductName, company.SubBranchName));
            }
        }
    }

    var groupedBySubBranchNameThenCompany = list.GroupByMany(p => p.SubBranchName, p => p.CompanyName);

    foreach (var groupResult in groupedBySubBranchNameThenCompany)
    {
        foreach (var result in groupResult.SubGroups)
        {
            foreach (var groupResult1 in result.Items)
            {
                Company company = groupResult1 as Company;
                Debug.Print(String.Format("SubBranchName: {0}, CompanyName: {1}", company.SubBranchName, company.CompanyName));
            }
        }
    }

The first "foreach" prints out

ProductName: Product1, SubBranchName: SB1
ProductName: Product1, SubBranchName: SB2
ProductName: Product2, SubBranchName: SB2
ProductName: Product2, SubBranchName: SB2
ProductName: Product2, SubBranchName: SB1
ProductName: Product3, SubBranchName: SB1
ProductName: Product3, SubBranchName: SB1
ProductName: Product3, SubBranchName: SB2
ProductName: Product4, SubBranchName: SB2
ProductName: Product4, SubBranchName: SB2

The second "foreach" prints out

SubBranchName: SB1, CompanyName: Company1
SubBranchName: SB1, CompanyName: Company1
SubBranchName: SB1, CompanyName: Company2
SubBranchName: SB1, CompanyName: Company3
SubBranchName: SB2, CompanyName: Company1
SubBranchName: SB2, CompanyName: Company2
SubBranchName: SB2, CompanyName: Company2
SubBranchName: SB2, CompanyName: Company2
SubBranchName: SB2, CompanyName: Company3
SubBranchName: SB2, CompanyName: Company3

Hope this helps!

Sign up to request clarification or add additional context in comments.

6 Comments

Maybe use IQueryable<TElement> and Expression<Func<TElement, object>> to be able to group "natively" and hook into the expression tree built and sent back to the DB?
And if I want to groupBy only one group without subgroups?
Well it's awesome evgeny, How do you pass the GroupByMany(p => p.DynamicField1, p => p.DynamicField2 ... p => p.DynamicFieldN);and do all the subgroup mining later dynamically? with for loop from strings or what? , The primary cause is to make generate a Company after the groupby and pass it to the view. thanks alot!
Another important thing, When you use: --- Company company = groupResult1 as Company; --- The whole company is filled and not only the fields which i wanted to groupby with, How can the company entity only have only the proper fields and leave the other null, etc? , Or should i just cluase the visibility for those fields in the view(The load time is better if only the needed grouped fields will be loaded!)
Also the company should be filled and not overided on the first raw every time.
|
1

I can't say exactly how relevant this is to your particular problem, but if you have a field you want to group your data on you can write a query similar to the following, which groups the blog posts on the year they were created in

var results = from allPosts in db.Posts.OrderBy(p => p.DateCreated)
              group allPosts by allPosts.DateCreated.Year into postsByYear;

The "results" here is the enumeration of groups - in this case, posts published in a certain year.

This can be further extended to create child groups within the "first level" - posts by the month groups similar to

var results = from allPosts in db.Posts.OrderBy(p => p.DateCreated)
              group allPosts by allPosts.DateCreated.Year into postsByYear

              select new
              {
                  postsByYear.Key,
                  SubGroups = from yearLevelPosts in postsByYear
                              group yearLevelPosts by yearLevelPosts.DateCreated.Month into postsByMonth;
              };

Now the SubGroups is the enumeration of posts within the month. There is more information here (may be very helpful)

http://blogs.msdn.com/b/mitsu/archive/2007/12/22/playing-with-linq-grouping-groupbymany.aspx

and here (my application of the previous link to a particular problem I had)

http://www.ynegve.info/Post/156/implementing-a-tree-view-small-case-study

If that looks like what you need, but you still can't make it work, please post more info about your model.

1 Comment

Hey Evgeny, Thank you for your time. I've made a more well explained post here: forums.asp.net/t/1885915.aspx/… Basicly, I have several fields that i want to pass as variable to the groupBy clause instead of hard-coded grouping by casing every possible scenerio. To be able to do something like : IEnumerable<Company> afs = cmpqry.GroupBy("CompanyName", "SubBranchName", "ProductName"); and afterward when users checks different fields ill be able to pass other values: IEnumerable<Company> afs = cmpqry.GroupBy("CompanyName", "SomeName");

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.