繁体   English   中英

按LINQ分组嵌套对象

[英]Group by linq for nested objects

我正在通过linq语句进行分组,其中我将单个数据列表转换为带有嵌套列表的列表。 到目前为止,这是我的代码:

[TestMethod]
public void LinqTestNestedSelect2()
{
    // initialization 
    List<combi> listToLinq = new List<combi>() { 
        new combi{ id = 1, desc = "a", name = "A", count = 1 },
        new combi{ id = 1, desc = "b", name = "A", count = 2 },
        new combi{ id = 2, desc = "c", name = "B", count = 3 },
        new combi{id = 2,  desc = "d", name = "B", count = 4 },
    };

    // linq group by
    var result = (from row in listToLinq
                  group new { des = row.desc, count = row.count } by new { name = row.name, id = row.id } into obj
                  select new A { name = obj.Key.name, id = obj.Key.id, descriptions = (from r in obj select new B() { des = r.des, count = r.count }).ToList() }).ToList();

    // validation of the results
    Assert.AreEqual(2, result.Count);
    Assert.AreEqual(2, result[0].descriptions.Count);
    Assert.AreEqual(2, result[0].descriptions.Count);
    Assert.AreEqual(2, result[1].descriptions.Count);
    Assert.AreEqual(2, result[1].descriptions.Count);
}

public class A
{
    public int id;
    public string name;

    public List<B> descriptions;
}

public class B
{
    public int count;
    public string des;
}

public class combi
{
    public int id;
    public string name;
    public int count;
    public string desc;
}

如果对象很小(如示例所示),这很好。 但是,我将为具有更多属性的对象实现此功能。 如何有效地编写此语句,这样我就不必在linq语句中两次写字段名称了?

我想返回语句中的对象,我想要这样的东西:

// not working wishfull thinking code 
var result = (from row in listToLinq
              group new { des = row.desc, count = row.count } by new { name = row.name, id = row.id } into obj
              select new (A){ this = obj.key , descriptions = obj.ToList<B>()}).ToList();

背景 :我正在写一个Web api,它在单个数据库调用中检索具有嵌套对象的对象,以提高数据库性能。 从本质上讲,这是一个带有联接的大查询,它检索我需要整理为对象的大量数据。
可能很重要 :ID是唯一的。

编辑:根据到目前为止的答案,我已经为我做了一种解决方案,但是仍然有点丑陋,我希望它看起来更好。

{
    // start part
    return (from row in reader.AsEnumerable()
            group row by row.id into grouping
            select CreateA(grouping)).ToList();
}

private static A CreateA(IGrouping<object, listToLinq> grouping)
{
     A retVal = StaticCreateAFunction(grouping.First());
    retVal.descriptions = grouping.Select(item => StaticCreateBFunction(item)).ToList();
    return ret;
}

我希望StaticCreateAFunction对于它所做的事情足够明显。 在这种情况下,我只需要写出每个属性一次,这正是我真正想要的。 但我希望有一种更聪明或更随意的方式来编写此代码。

var result = (from row in listToLinq
              group new B { des = row.desc, count = row.count } by new A { name = row.name, id = row.id } into obj
              select new A { name = obj.Key.name, id = obj.Key.id, descriptions = obj.ToList() }).ToList();

您可以向AB类中的每个类添加一个构造函数,该构造函数接收一个combi ,然后仅从其中获取所需的内容。 例如,对于a

public class A
{
    public A(combi c)
    {
        id = c.id;
        name = c.name;
    }
}   

public class B
{
    public B(combi c)
    {
        count = c.count;
        des = c.desc;
    }
}

然后,您的查询如下所示:

var result = (from row in listToLinq
              group row by new { row.id, row.name } into grouping
              select new A(grouping.First())
              {
                  descriptions = grouping.Select(item => new B(item)).ToList()
              }).ToList();

如果你不喜欢grouping.First()然后你可以重写EqualsGetHashCode ,然后在group by通过新做的a与相关领域(这将是那些在Equals ),然后添加一个copy constructora

combi分离A / B类的另一种方法是将转换逻辑提取到静态方法的集合中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM