如何使用一个具体类进行多个分组
本文关键字:何使用 一个 | 更新日期: 2023-09-27 18:28:37
我有这样的场景。
我想要国家和类别组。
A store can have many countries and a country can have many stores. (many to many)
A store can have many categories and a category can have many stores (many to many)
假设我有这些类别
Food
Gas
Car Shop
我有这些商店
Pizza Hut
Canadian Tire
Shell
我有这些国家
Canada
USA
所以最后它应该看起来像这个
Canada
Food
Pizza Hut
Gas
Canadian Tire (some places have gas stations)
Shell
Car Shop
Canadian Tire
USA
Food
Pizza Hut
Gas
Shell
Car Shop
(nothing in my example as Canadian Tire is only in Canada)
以上就是我想向用户展示的最终结果。我现在被困在linq中的分组上(我也在使用nhibernate)
session.Query<Store>().FetchMany(x => x.Countries).FetchMany(x => x.Categories).GroupBy(x => new {x.Countires, x.Categories})
上面会给我一个匿名类,但我需要从服务层返回结果,然后使用它们来创建我的视图Model。
所以我不能使用匿名类。
我不知道如何制作我的混凝土课?
里面需要像伊格鲁平一样的东西吗?
如果您定义了一个具有正确属性的类,比如MyClass,并且适当的构造函数可以在查询中使用新的MyClass(x.Countrys,x.Categories),而不是匿名类型构造函数。
或者,您可以只使用不带参数的默认构造函数,并使用正常的C#属性初始化语法。不过,我的手机不会使用花括号,所以我不能发布代码片段:-(
您得到一个匿名类,因为您使用的是GroupBy方法。IQueryable
中的GroupBy的工作方式几乎与SQL GROUP BY
子句类似。为了更好地理解分组,您必须考虑SQL GROUP BY只能与多对一运算符(如SUM
、AVG
、MAX
、MIN
)一起使用,因为它们从行集中返回单个结果。在我看来,您的"分组"概念是GUI上的可视化分组。
选择所有人(Name、Surname)和GROUP BY
姓氏是没有意义的,因为在最终结果中选择要投影的名字是模糊的。
GroupBy运算符正是您不希望使用的运算符。如果你正确地建立了多对一+多对一的关系(形成了多对多),那么你应该有类似的东西
public class Country{
Store[] stores;
}
public class Store {
Category[] categories;
Country[] countries;
}
public class Category {
Store[] stores;
}
对值进行"分组"的最佳方法是使用普通的旧for
循环。这是pseuso-C#代码
for (Country co in session.Query<Country>()) {
Console.WriteLine(co); //Possibly c.Name or whatever
Console.Indentation++; //.NET has not such a method but you understand what it means
for (Category ca in co.Categories) {
Console.WriteLine(ca);
Console.Indentation++;
for (Store s in ca.Stores) {
Console.WriteLine(s);
}
Console.Indentation--;
}
Console.Indentation--;
}
[添加]反向查找的示例,如果您的模型显示有参考类别->国家而不是国家->类别,则该示例适用
for (Country co in session.Query<Country>()) {
Console.WriteLine(co);
Console.Indentation++;
for (Category ca in session.Query<Category>().Where(x => x.Country.equals(co))) {
Console.WriteLine(ca);
//snip
}
Console.Indentation--;
}