Asp.net mvc 如何在Mvc中使用Linq动态查找递归父子层次结构
我可以在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
**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 );