【问题标题】:Create GroupBy Statments Dynamically By Strings Array - Linq to Entity通过字符串数组动态创建 GroupBy 语句 - Linq to Entity
【发布时间】:2013-02-26 08:56:15
【问题描述】:

我有一个动作可以加载一个字符串数组,这些字符串由页面上相应的复选框选中:

        public ActionResult Test1(string[] checked_strings)

我想使用与我想动态创建 groupby 语句的实体名称相同的字符串。

会发生这样的事情:

            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 //

知道如何解决这个问题吗?

cmpqry 保存模型类的 IEnumarable 列表(稍后返回查看)。

【问题讨论】:

  • 动态 linq 可能是您的答案,stackoverflow.com/questions/2448611/…
  • 已经尝试过了,我无法将其转换回 EF 模型并将其正确列出到视图中。如果你认为有可能,我想要一个例子。谢谢。
  • 无法设法使用动态 linq 的“GroupBy”,它会从这个例子中抛出异常: var groups = Model.GroupBy("SomeColumn, SomeOtherColumn") 即使在我添加了库文件 DynamicLibrary.cs - 请帮助!!

标签: c# asp.net-mvc linq entity-framework group-by


【解决方案1】:

这是有效的代码示例 - 您应该能够按照您希望它们分组的顺序提供要分组的字段:

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));
            }
        }
    }

第一个“foreach”打印出来

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

第二个“foreach”打印出来

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

希望这会有所帮助!

【讨论】:

  • 也许使用IQueryable&lt;TElement&gt;Expression&lt;Func&lt;TElement, object&gt;&gt; 能够“本地”分组并挂钩到构建并发送回数据库的表达式树?
  • 如果我只想分组一个没有子组的组?
  • 这真是太棒了,你如何通过 GroupByMany(p => p.DynamicField1, p => p.DynamicField2 ... p => p.DynamicFieldN); 并进行所有子组挖掘后来动态?用字符串中的for循环还是什么? , 主要原因是在groupby之后生成一个公司并将其传递给视图。非常感谢!
  • 另一件重要的事情,当你使用:--- Company company = groupResult1 as Company; --- 整个公司都被填满了,而不仅仅是我想要分组的字段,公司实体如何只有正确的字段而其他字段为空,等等? , 或者我应该只在视图中包含这些字段的可见性(如果只加载所需的分组字段,加载时间会更好!)
  • 另外,公司应该被填满,而不是每次都在第一个 raw 时被覆盖。
【解决方案2】:

我不能确切地说这与您的特定问题有多大的相关性,但如果您有一个字段要对您的数据进行分组,您可以编写一个类似于以下内容的查询,它将博客文章分组在他们的年份创建于

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

这里的“结果”是组的枚举——在这种情况下,是某年发布的帖子。

这可以进一步扩展以在“第一级”内创建子组 - 类似于

的月份组的帖子
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;
              };

现在 SubGroups 是一个月内帖子的枚举。 这里有更多信息(可能很有帮助)

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

在这里(我将上一个链接应用于我遇到的特定问题)

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

如果这看起来像您需要的,但您仍然无法使其工作,请发布有关您的模型的更多信息。

【讨论】:

  • 嗨 Evgeny,感谢您抽出宝贵时间。我在这里做了一个解释得更清楚的帖子:forums.asp.net/t/1885915.aspx/… 基本上,我有几个字段我想作为变量传递给 groupBy 子句,而不是通过每个可能的场景进行硬编码分组。能够执行以下操作: IEnumerable afs = cmpqry.GroupBy("CompanyName", "SubBranchName", "ProductName");之后,当用户检查不同的字段时,将无法传递其他值: IEnumerable afs = cmpqry.GroupBy("CompanyName", "SomeName");
猜你喜欢
  • 2019-01-10
  • 2014-12-05
  • 2014-01-09
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 2016-12-08
相关资源
最近更新 更多