簡體   English   中英

遞歸linq結果返回重復項

[英]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類中實現GetHashCodeEquals 但總的來說,我不喜歡遞歸子級檢索的實現和Union的使用-必須有更好的方法,但這不在此問題的范圍內(但對於鏈接而言)。

對我來說,邪惡的根源在於以下條件

where l.ParentLocationID == parentId || l.LocationID == parentId

它同時選擇了項目及其子項,從而導致結果集中出現重復項,然后應通過Union方法消除這些重復項。 好的實現根本不會生成重復項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM