Asp.net mvc 如何在Mvc中使用Linq动态查找递归父子层次结构

Asp.net mvc 如何在Mvc中使用Linq动态查找递归父子层次结构,asp.net-mvc,linq,linq-to-sql,Asp.net Mvc,Linq,Linq To Sql,我可以在linq中动态查找父子关系吗 当用户提供子输入时,我们必须找出子输入的直接父项和顶级父项 模式: **LocationId** **LocationName** **ParentId** 1 InterNational 0 2 National 1 3 Regional 2 4 SubRe

我可以在linq中动态查找父子关系吗

当用户提供子输入时,我们必须找出子输入的直接父项和顶级父项

模式:

**LocationId**   **LocationName**  **ParentId**
 1               InterNational          0
 2                National              1
 3                Regional              2
 4                SubRegional           3
 5                Area                  4
 6                City                  5
 7                Town                  6
 8              Municipality            7



Input:When user type input as Area
Outpt:immediate parent: SubRegional
Top parent:International
total parent:4

if:town
immediate parent:City
top parent:international
total parent:6
阶级

视图:

@model IEnumerable
@{
ViewBag.Title=“家长子女”;
}
亲子
@foreach(模型中的var x)
{
currentLocationName:@x.LocationName

currentLocationId:@x.LocationId

LocationTopParentId:@x.parentId

LocationTopParent:@x.ParentName

LocationimmediateparentId:@x.immediateparentId

LocationImmediatePartnerName:@x.ImmediatePartnerName


}
我会使用linq将数据放入字典中,然后进行简单的搜索和查找

void Main()
{

  List<loc> basedata = new List<loc>() 
  {
     new loc() { ID = 1, name = "InterNational", pID = 0 },
     new loc() { ID = 2, name = "National", pID = 1 },
     new loc() { ID = 3, name = "Regional", pID = 2 },
     new loc() { ID = 4, name = "SubRegional", pID = 3 },
     new loc() { ID = 5, name = "Area", pID = 4 },
     new loc() { ID = 6, name = "City", pID = 5 },
     new loc() { ID = 7, name = "Town", pID = 6 },
     new loc() { ID = 8, name = "Municipality", pID = 7 },
  };

  Dictionary<int,loc> data = basedata.ToDictionary(x => x.ID);

  string test1 = "Area";

  loc test1parent = data[data.First(x => x.Value.name == test1).Value.pID];
  loc top1;
  for(top1 = data.First(x => x.Value.name == test1).Value;top1.pID!=0;top1 = data[top1.pID]);

  Console.WriteLine("Immediate Parent = "+test1parent.name);
  Console.WriteLine("Top parent = "+top1.name);

  string test2 = "Town";

  loc test2parent = data[data.First(x => x.Value.name == test2).Value.pID];
  loc top2;
  for(top2 = data.First(x => x.Value.name == test2).Value;top2.pID!=0;top2 = data[top2.pID]);

  Console.WriteLine("Immediate Parent = "+test2parent.name);
  Console.WriteLine("Top parent = "+top2.name);

}


public class loc
{
   public int ID { get; set; }
   public string name { get; set; }
   public int pID { get; set; }
}
void Main()
{
List basedata=新列表()
{
new loc(){ID=1,name=“InterNational”,pID=0},
new loc(){ID=2,name=“National”,pID=1},
new loc(){ID=3,name=“Regional”,pID=2},
new loc(){ID=4,name=“subsectional”,pID=3},
new loc(){ID=5,name=“Area”,pID=4},
new loc(){ID=6,name=“City”,pID=5},
new loc(){ID=7,name=“Town”,pID=6},
new loc(){ID=8,name=“市政”,pID=7},
};
Dictionary data=basedata.ToDictionary(x=>x.ID);
string test1=“区域”;
loc test1parent=data[data.First(x=>x.Value.name==test1.Value.pID];
loc top1;
for(top1=data.First(x=>x.Value.name==test1.Value;top1.pID!=0;top1=data[top1.pID]);
Console.WriteLine(“直接父项=“+test1parent.name”);
Console.WriteLine(“Top parent=“+top1.name”);
字符串test2=“Town”;
loc test2parent=data[data.First(x=>x.Value.name==test2.Value.pID];
loc top2;
for(top2=data.First(x=>x.Value.name==test2.Value;top2.pID!=0;top2=data[top2.pID]);
Console.WriteLine(“直接父项=“+test2parent.name”);
Console.WriteLine(“Top parent=“+top2.name”);
}
公共类loc
{
公共int ID{get;set;}
公共字符串名称{get;set;}
公共int-pID{get;set;}
}

可重用的东西可能是这样的

public static class MyExtensions
    {
        public static List<T> Parents<T>(this List<T> list, T current, Func<T, int> getId, Func<T, int> getPid)
        {
            List<T> returnlist = new List<T>();

            T temp = list.FirstOrDefault(x => getPid(current) == getId(x));
            while (temp != null)
            {
                returnlist.Add(temp);
                current = temp;
                temp = list.FirstOrDefault(x => getPid(current) == getId(x));
            }

            return returnlist;
        }
    }

您不提供任何关于所使用的内部数据结构的信息,只显示数据模型。如果您希望得到可用的结果,请提供这些详细信息。这甚至不是一个模型,只是一个表架构。我建议将您的parentId International更改为null,而不是0。然后在表上设置自引用外键约束(ParentId必须指向同一表中的有效id),然后更新数据上下文。然后,您应该在
ParentChild
类上有一个名为
Parent
的属性,您可以在其中引用直接的父级。我已经删除了我的答案,但这基本上与我10分钟前的答案相同,但是构建了自己的查找,而不是让LINQ自动执行。我意识到OP不可能使用LINQs自动生成虚拟属性,因为他的表设置得很奇怪。他使用0表示无父项而不是null,这意味着他不可能在表上正确设置引用完整性(不存在id为0的记录),并且我认为LINQ也不会出于相同的原因允许您设置导航属性@RobertMcKee-是的,我同意-他的示例代码还有其他奇怪的地方,在ParentChild类中有一个列表对我来说毫无意义(考虑到其他属性)。我写的答案是独立的,这可能会被证明是有帮助的。这很可爱——很难创建一个通往顶端的路径列表。它也可以在没有使用聚合的扩展的情况下实现
@model IEnumerable <Dataclasses.ParentChildViewModel>


@{
    ViewBag.Title = "ParentChilds";
}

<h2>ParentChilds</h2>

@foreach (var x in Model)
{
   <p>currentLocationName: @x.LocationName</p>
    <p>currentLocationId :@x.LocationId</p>

    <p>LocationTopParentId :@x.parentId</p>
   <p>LocationTopParent:@x.ParentName</p>

<p>LocationimmediateparentId :@x.immediateparentId</p>
   <p>LocationimmediateparentName:@x.immediateparentName</p>
    <br />

}
void Main()
{

  List<loc> basedata = new List<loc>() 
  {
     new loc() { ID = 1, name = "InterNational", pID = 0 },
     new loc() { ID = 2, name = "National", pID = 1 },
     new loc() { ID = 3, name = "Regional", pID = 2 },
     new loc() { ID = 4, name = "SubRegional", pID = 3 },
     new loc() { ID = 5, name = "Area", pID = 4 },
     new loc() { ID = 6, name = "City", pID = 5 },
     new loc() { ID = 7, name = "Town", pID = 6 },
     new loc() { ID = 8, name = "Municipality", pID = 7 },
  };

  Dictionary<int,loc> data = basedata.ToDictionary(x => x.ID);

  string test1 = "Area";

  loc test1parent = data[data.First(x => x.Value.name == test1).Value.pID];
  loc top1;
  for(top1 = data.First(x => x.Value.name == test1).Value;top1.pID!=0;top1 = data[top1.pID]);

  Console.WriteLine("Immediate Parent = "+test1parent.name);
  Console.WriteLine("Top parent = "+top1.name);

  string test2 = "Town";

  loc test2parent = data[data.First(x => x.Value.name == test2).Value.pID];
  loc top2;
  for(top2 = data.First(x => x.Value.name == test2).Value;top2.pID!=0;top2 = data[top2.pID]);

  Console.WriteLine("Immediate Parent = "+test2parent.name);
  Console.WriteLine("Top parent = "+top2.name);

}


public class loc
{
   public int ID { get; set; }
   public string name { get; set; }
   public int pID { get; set; }
}
public static class MyExtensions
    {
        public static List<T> Parents<T>(this List<T> list, T current, Func<T, int> getId, Func<T, int> getPid)
        {
            List<T> returnlist = new List<T>();

            T temp = list.FirstOrDefault(x => getPid(current) == getId(x));
            while (temp != null)
            {
                returnlist.Add(temp);
                current = temp;
                temp = list.FirstOrDefault(x => getPid(current) == getId(x));
            }

            return returnlist;
        }
    }
var locations = ParentChild.LocationParent();
            var parents = locations.Parents(locations[6], x => x.LocationId, x => x.parentId);
            Console.WriteLine( "Immediate Parent {0}, top - parent:{1}, count : {2}",
            parents.First().LocationName,
            parents.Last().LocationName,
            parents.Count );