我是linq的新手,我正在尝试找到一种方法来返回父级和一个List(子级)以及所有这些子级,用于给定的父级。我有一个地点表,其中包含字段LocationID
,ParentLocationID
,LocationName
。数据样本可能如下所示:
ABC
--ABC1
--ABC2
----DEF1
----DEF2
----DEF3
--ABC3
----DEF4
------GHI1
------GHI2
----DEF5
--ABC4
...
鉴于该数据,如果所选父项是'ABC',我想返回所有行,因为所有子项都在其下。但是,如果我选择了父'ABC3',它将返回DEF4,GHI1,GHI2,DEF5。
我已经研究了这些SO问题,但我仍然对如何创建这个语句感到困惑:
Find all descendants in self-referencing (parent-child) hierarchical tree
LINQ to SQL - Self Join Child to Parent (Same Table)
这是我尝试过的但是收到错误:
public ActionResult Index()
{
var loc = GetChild(346);
return View(loc);
}
public IEnumerable<Location> GetChild(int id)
{
DBEntities db = new DBEntities();
var locations = db.Locations.Where(x => x.ParentLocationID == id || x.LocationID == id).Union(
db.Locations.Where(x => x.ParentLocationID == id).SelectMany(y => GetChild(y.LocationID)));
return locations;
}
Location
类是:
public class Location
{
public Location();
public virtual ICollection<SimSystem> SimSystems { get; set; }
public virtual ICollection<LocationAddress> LocationAddresses { get; set; }
public virtual LocationType LocationType { get; set; }
public virtual ICollection<CustomerUser> CustomerUsers { get; set; }
public virtual ICollection<AppUserLocation> AppUserLocations { get; set; }
public int LocationTypeID { get; set; }
public DateTime? InstallDate { get; set; }
public string AltPhone { get; set; }
public string OfficePhone { get; set; }
public int? PrimaryAddressID { get; set; }
public int? ParentLocationID { get; set; }
public string LocationName { get; set; }
public string LocationName2 { get; set; }
public int LocationID { get; set; }
public virtual Address Address { get; set; }
}
错误是:
LINQ to Entities无法识别该方法,并且此方法无法转换为商店表达式。
答案 0 :(得分:1)
你可以试试吗..
{{1}}
答案 1 :(得分:0)
首先,您需要让DBEntities
退出递归方法。您最终会在数据库上建立太多连接,最终会导致内存泄漏
至于例外。它声明对GetChild(int);
的调用无法转换为linq到sql表达式。如果您有要生成的sql,我可以帮助您将其翻译为linq。
编辑:
所以我能够重新创建你的代码。这不是最佳的,因为它将使用sql查询多次调用数据库。
public class Recursive
{
BlogContext db = new BlogContext();
public int Counter { get; set; } = 0;
public Recursive()
{
db.Database.Log += (str) => //this will log all the calls to the database.
{
System.Diagnostics.Debug.WriteLine(str, "Sql Query: ");
};
}
public List<Location> StartRecursive()
{
return GetChild(50).ToList();
}
public IEnumerable<Location> GetChild(int id)
{
var locations = db.Locations
.Where(x => x.ParentLocationID == id || x.LocationID == id).ToList();
if (locations.Count == 1) return locations;
var locationSubset = locations.Where(tt=>tt.LocationID!=id)
.SelectMany(tt => GetChild(tt.LocationID)).ToList();
Counter++;
return locations.Union(locationSubset);
}
答案 2 :(得分:0)
因此,在尝试自己弄清楚并且失败时,我做了一些研究。我遇到的大多数文章都表示,在使用Linq的单个查询中,这是不可能的。
您可以做的一件事是收集层次结构中对象的所有ID。然后只抓取你需要的对象,然后用它在内存中用对象构建一个树。抓取ID应该非常快,特别是对于索引。
e.g。 List<int> locationIDs = db.Locations.Where(x => x.ParentLocationID == id || x.LocationID == id).Select(x => x.LocationID).ToList();
然后你可以
var locations = db.Locations.Where(x => locationIDs.Contains(x.LocationID);
然后使用普通的递归方法构建树。 不过我还想提一个我发现的扩展方法,据说可以为你做这个。使用信息图表等描述非常详细。 http://www.scip.be/index.php?Page=ArticlesNET23