[英]Recursive linq results returning duplicates
這個問題基於我上周提出的一個問題: 遞歸linq來獲得無限個孩子 。 那篇文章給出的答案滿足了我的需求。 基於父項的位置及其子項的明確列表。 我們需要對位置使用自己的模型,因此我們創建了一個模型,從那時起,我一直得到重復的結果。 我們的模型非常基礎:
class LocationModel
{
public int LocationID { get; set; }
public int ParentLocationID { get; set; }
public string LocationName { get; set;}
}
如果您將其與EF創建的實體進行比較,則只刪除了我們不需要/不使用的所有字段(請參見上面的鏈接)。 因此,我修改了linq語句以使用此新模型:
DBEntities db = new DBEntities();
public IEnumerable<LocationModel> GetAllChildLocations(int parentId)
{
var locations = (from l in db.Locations
where l.ParentLocationID == parentId ||
l.LocationID == parentId
select new LocationModel()
{
LocationID = l.LocationID,
ParentLocationID = l.ParentLocationID,
LocationName = l.LocationName
}).ToList();
var children = locations.AsEnumerable()
.Union(db.Locations.AsEnumerable()
.Where(x => x.ParentLocationID == parentId)
.SelectMany(y => GetAllChildLocations(y.LocationID)))
.ToList();
return children.OrderBy(l => l.LocationName);
}
在Visual Studio或LinqPad中運行它時,我現在得到了重復項。 這里是原來的代碼不產生重復:
public IEnumerable<Location> GetAllChildLocations(int parentId)
{
var locations = (from l in db.Locations
where l.ParentLocationID == parentId ||
l.LocationID == parentId
select l).ToList();
var child = locations.AsEnumerable()
.Union(db.Locations.AsEnumerable()
.Where(x => x.ParentLocationID == parentId)
.SelectMany(y => GetAllChildLocations(y.LocationID)))
.ToList();
return child;
}
為什么使用我自己的模型而不是EF生成的模型會產生重復? 它是否與EF模型具有的自動生成字段有關,而我的沒有?
為什么使用我自己的模型而不是EF生成的模型會產生重復?
因為您使用的是Enumerable.Union
方法,默認情況下使用引用相等。 EF DbContext
更改跟蹤器在內部(跟蹤)具有相同PK的已加載實體對象實例(即使您通過單獨的數據庫查詢檢索它們也是如此),因此引用相等性起作用。 對於查詢select
運算符創建的new LocationModel
實例,不能說哪個。
解決它的一種方法是在LocationModel
類中實現GetHashCode
和Equals
。 但總的來說,我不喜歡遞歸子級檢索的實現和Union
的使用-必須有更好的方法,但這不在此問題的范圍內(但對於鏈接而言)。
對我來說,邪惡的根源在於以下條件
where l.ParentLocationID == parentId || l.LocationID == parentId
它同時選擇了項目及其子項,從而導致結果集中出現重復項,然后應通過Union
方法消除這些重復項。 好的實現根本不會生成重復項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.