我有一些表示同一实体上的父子关系的数据。给定一个节点,我需要找到它的整个上层层次结构(父、祖父母、曾祖父母等)。
我的实体是这样的:
public partial class Location{
public int LocationId { get; set; }
public int? FkParentLocationId { get; set; }
..... more properties here.......
public virtual Location FkParentLocation { get; set; }
public virtual ICollection<Location> InverseFkParentLocation { get; set; }
}我指的是here建议的层次结构遍历实现,但它在向下层次结构时起作用。如何使用LINQ检索上层层次结构?
示例数据:
List<Location> locations = new List<Location> {
new Location { LocationId = 5, FkParentLocationId = 3, LocationName = "Windsor", LocationDisplayName = "Windsor"},
new Location { LocationId = 15, FkParentLocationId = 3, LocationName = "Hampshire", LocationDisplayName = "Hampshire" },
new Location { LocationId = 12, FkParentLocationId = 3, LocationName = "Sussex", LocationDisplayName = "Sussex"},
new Location { LocationId = 13, FkParentLocationId = 3, LocationName = "Willowood", LocationDisplayName = "Willowood"},
new Location { LocationId = 1, FkParentLocationId = 3, LocationName = "Gerbshire", LocationDisplayName = "Gerbshire"},
new Location { LocationId = 3, FkParentLocationId = 2, LocationName = "Lincoln", LocationDisplayName = "Lincoln"},
new Location { LocationId = 2, LocationName = "Mains", LocationDisplayName = "Mains" } };预期输出:给定位置Id:5,我应该会得到一个包含位置3和2的列表(因为它们是父级)。
发布于 2019-12-25 01:10:46
这是一种你可以使用的方法,使用控制台应用程序进行演示。大量向Jon Skeet借钱。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Locations
{
public partial class Location
{
public int LocationId { get; set; }
public int? FkParentLocationId { get; set; }
public virtual Location FkParentLocation { get; set; }
public virtual ICollection<Location> InverseFkParentLocation { get; set; }
public string LocationName { get; set; }
public string LocationDisplayName { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<Location> locations = new List<Location> {
new Location { LocationId = 5, FkParentLocationId = 3, LocationName = "Windsor", LocationDisplayName = "Windsor"},
new Location { LocationId = 15, FkParentLocationId = 3, LocationName = "Hampshire", LocationDisplayName = "Hampshire" },
new Location { LocationId = 12, FkParentLocationId = 3, LocationName = "Sussex", LocationDisplayName = "Sussex"},
new Location { LocationId = 13, FkParentLocationId = 3, LocationName = "Willowood", LocationDisplayName = "Willowood"},
new Location { LocationId = 1, FkParentLocationId = 3, LocationName = "Gerbshire", LocationDisplayName = "Gerbshire"},
new Location { LocationId = 3, FkParentLocationId = 2, LocationName = "Lincoln", LocationDisplayName = "Lincoln"},
new Location { LocationId = 2, LocationName = "Mains", LocationDisplayName = "Mains" } };
var result = GetAncestorsIds(locations, 5);
foreach (var id in result)
{
System.Console.WriteLine(id);
}
}
private static IEnumerable<int> GetAncestorsIds(List<Location> locations, int id)
{
Location location = locations.SingleOrDefault(l => l.LocationId == id);
if(location != null)
{
while(location != null && location.FkParentLocationId != null)
{
location = locations.SingleOrDefault(l => l.LocationId == location.FkParentLocationId);
if(location != null)
{
yield return location.LocationId;
}
}
}
}
}
}这种方法可以转化为您自己的Linq扩展。这是它可能看起来的样子。
public static class MyExtensions
{
public static IEnumerable<int> GetAncestorIds<TSource>(this IEnumerable<TSource> source, Func<TSource, int> pk, Func<TSource, int?> fk, int id)
{
TSource currentObj = source.SingleOrDefault(s => pk(s) == id);
while(currentObj != null && fk(currentObj) != null)
{
currentObj = source.SingleOrDefault(s => pk(s) == fk(currentObj));
if(currentObj != null)
{
yield return pk(currentObj);
}
}
}
}然后在你的场景中调用它,你可以这样做
var result = locations.GetAncestorIds(l => l.LocationId, l => l.FkParentLocationId, 5);https://stackoverflow.com/questions/59370362
复制相似问题