Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# GroupJoin产生了非常令人惊讶的结果_C#_Entity Framework - Fatal编程技术网

C# GroupJoin产生了非常令人惊讶的结果

C# GroupJoin产生了非常令人惊讶的结果,c#,entity-framework,C#,Entity Framework,我有一个如下所示的数据库表: MenuItemID | int [Primary Key] 1 -----+ MenuItemName | nvarchar(100) | ParentID | int * -----+ 正如您在上面的示意图中所看到的,ParentID列指的是MenuItemID,因此我们可以获得分层输出 上表中的样本数据如下所示: MenuItemI

我有一个如下所示的数据库表:

MenuItemID       |    int   [Primary Key]   1 -----+
MenuItemName     |    nvarchar(100)                |
ParentID         |    int                   * -----+
正如您在上面的示意图中所看到的,ParentID列指的是MenuItemID,因此我们可以获得分层输出

上表中的样本数据如下所示:

MenuItemID       |    int   [Primary Key]   1 -----+
MenuItemName     |    nvarchar(100)                |
ParentID         |    int                   * -----+

根据上面的示例数据,我希望输出如下:

Electronics
    Mobile
    Desktop
    Laptop
        Lenovo
        Dell
Sports
    Cricket
    Football
    Hockey
Stationary
    Books
    Pens
    Pencils
    Erasers
我尝试过的:

我尝试了下面提到的代码,其中我尝试使用GroupJoin扩展方法来实现所需的输出:

class Program
{
    static void Main(string[] args)
    {
        OnlineShoppingEntities db = new OnlineShoppingEntities();

        var x = db.MenuItems.GroupJoin(db.MenuItems,
                                       m => m.MenuItemID,
                                       m => m.ParentID,
                                       (parentMenuItems, childMenuItems) => new
                                       {
                                           ParentMenuItems = parentMenuItems,
                                           ChildMenuItems = childMenuItems
                                       });

        foreach (var v in x)
        {
            Console.WriteLine(v.ParentMenuItems.MenuItemName);
            foreach (var m in v.ChildMenuItems)
            {
                Console.WriteLine("\t" + m.MenuItemName);
            }
        }
    }
}
我得到的输出:


我对输出感到非常惊讶,因为我期望得到如上所述的所需输出。

您的解决方案可以在以下位置找到:

我不会抽象代码,因为有太多的答案可以解决您的问题,我特别喜欢
AsHierarchy()
linq扩展方法,如对该问题的回答所示

var hierachy = dc.Employees.ToList().AsHierarchy(e => e.EmployeeID, e => e.ReportsTo);
最重要的是:

使用系统;
使用System.Collections.Generic;
使用System.Linq;
命名空间ScipBe.Common.LinqExtensions
{
//斯特凡·克鲁斯伯格,http://www.scip.be,2008年3月
/// 
///包含层次结构节点嵌套集合的层次结构节点类
/// 
///实体
公共类层次结构节点,其中T:class
{
公共T实体{get;set;}
公共IEnumerable子节点{get;set;}
公共整数深度{get;set;}
}
公共静态类LinqExtensionMethods
{
私有静态System.Collections.Generic.IEnumerable CreateHierarchy
(i可数Allitem,TEntity parentItem,
Func idProperty,Func parentIdProperty,int-depth),其中tenty:类
{ 
数不清的孩子;
if(parentItem==null)
childs=allItems.Where(i=>parentIdProperty(i).Equals(default(TProperty));
其他的
childs=allItems.Where(i=>parentIdProperty(i).Equals(idProperty(parentItem));
如果(childs.Count()>0)
{
深度++;
foreach(childs中的变量项)
yield返回新的HierarchyNode(){Entity=item,ChildNodes=CreateHierarchy
(allItems,item,idProperty,parentIdProperty,depth),depth=depth};
}
}
/// 
///LINQ IEnumerable AsHierachy()扩展方法
/// 
///实体类
///实体类的性质
///实体的平面集合
///对实体Id/密钥的引用
///对父Id/密钥的引用
///实体的层次结构
公共静态System.Collections.Generic.IEnumerable AsHierarchy
(此IEnumerable Allitem、Func idProperty、Func parentIdProperty)
地点:班级
{
返回CreateHierarchy(allItems,默认值(tenty),idProperty,parentIdProperty,0);
}
}
}

当然,如果您的数据只有3个级别,为了简单起见,您可以使用其他
GroupJoin()

var hierarchical = menuItems.Where(m => m.ParentID == null)
                                .GroupJoin(menuItems,
                                            m => m.MenuItemID, 
                                            m => m.ParentID,
                                            (parentMenuItems, childMenuItems) => new
                                            {
                                                ParentMenuItems = parentMenuItems,
                                                ChildMenuItems = childMenuItems.GroupJoin(menuItems,
                                                m => m.MenuItemID, 
                                                m => m.ParentID,
                                                (subParentMenuItems, subChildMenuItems) => new
                                                {
                                                    ParentMenuItems = subParentMenuItems,
                                                    ChildMenuItems = subChildMenuItems
                                                })
                                            });

    foreach(var menu in hierarchical)
    {
        Console.WriteLine(menu.ParentMenuItems.MenuItemName);
        foreach(var submenu in menu.ChildMenuItems)
        {
            Console.WriteLine("\t" + submenu.ParentMenuItems.MenuItemName);
            foreach(var subitem in submenu.ChildMenuItems)
            {
                Console.WriteLine("\t\t" + subitem.MenuItemName);
            }
        }
    }

你实际上是在要求一个可传递的关系。。。你是怎么期望的?从根本上说,SQL不擅长表达这类东西,LINQ也不擅长表达。@JonSkeet如果我使用两个不同的表,那么我可以获得视频中提到的输出:@JonSkeet我应该使用什么来获得这种输出?我问这个问题是因为你刚才提到SQL不擅长表达这种东西,LINQ也不擅长。我不想看一个21分钟的视频来看看你做了什么。。。但我怀疑,即使有两个表,也无法轻松获取任意嵌套的组。不过,您可能想看看。您可能应该从数据库中以列表的形式检索所有必需的项,并在应用程序端创建层次关系。谢谢。您的两个答案都非常有用,但我将使用asherarch()linq扩展方法,因为级别不是固定的。为了得到输出,我使用了一个递归函数。但唯一的问题是我不知道:如何增加子菜单的左边距,以便在子菜单项的名称前看到一些空格。这样我就可以知道什么才是真正的父项,谁才是真正的子项。您将拥有
Depth
属性来了解项目的级别。此扩展返回的项的类型为
HierarchyNode
,因此您将有一个
实体
属性来获取实际项,一个
ChildNodes
属性来获取其子项,一个
深度
属性来获取其层次结构中的深度/级别。