簡體   English   中英

IQueryable 上的 EF Distinct 不會刪除重復項

[英]EF Distinct on IQueryable doesn't remove duplicates

我有一個通用類,它應該通過調用此方法來過濾、排序、投影和分頁IQueryable

public async Task<PagedResult<TResult>> GetFilteredOrderedPageAsync<TResult>(IQueryable<TSource> source,
            IFilterModel filterModel,
            ISortModel sortModel,
            int page, int pageSize,
            Expression<Func<TSource, TResult>> converter)
            where TResult : class 
        {
            var filtered = Filter(source, filterModel);

            var projected = filtered
                .Select(converter)
                .Distinct();

            var ordered = Sort<TResult>(projected, sortModel);

            var result = await GetPageAsync<TResult>(ordered, page, pageSize, converter);

            return result;
        }

我在這里調用Distinct()

        var projected = filtered
            .Select(converter)
            .Distinct();

刪除投影后可能出現的任何重復項。

我的假設是 EF6 會產生類似

SELECT DISTINCT Col1, Col2, Col3 FROM (SELECT Col1, Col2, Col3, Col4 FROM SOME_TABLE WHERE <some conditions on co1, col2, col3, col4 ...>)

即它會將DISTINCT應用於投影,因此,如果有兩行具有相同的 col1、col2、col3 但 col4 不同,則只有一行會使其成為結果。 但是,我得到的 SQL 如下所示:

SELECT Col1, Col2, Col3, Col4 FROM (SELECT DISTINCT Col1, Col2, Col3, Col4 FROM SOME_TABLE)

- 沒有投影,並且 DISTINCT 被轉移到子查詢中,就好像我在這樣做:

var projected = filtered                    
                .Distinct()
                .Select(converter) 

我希望這個服務是通用的,即可能與任何TSourceTResult一起工作,但看起來這里有一些陷阱,我對 EF 所做的事情的理解是不正確的。

這里發生了什么?

更新

我相信問題出在我的轉換器上。 我使用以下函數生成傳遞給Select的 lambda 表達式:

public class ProvidersViewModel
{
    public string Name { get; set; }
    public Rate Rate { get; set; } 
    publi QA QA { get; set; }
    ...
    public static Expression<Func<ProviderJoinRateAndQA, ProvidersViewModel>> FromProvider(bool showRateAndQA) 
    {
       return x => new ProvidersViewModel {
        Name = x.Name, 
        Rate = showRateAndQA ? new Rate { Amount = x.Rate.Amount ... } : null,
        Rate = showRateAndQA ? new QA { Grade = x.QA.Grade ... } : null
    };
}

}

ProviderJoinRateAndQA是提供者、他們的費率和 QA 的連接。 每個Provider可以有多種服務、費率和質量保證。 在某些情況下,我希望視圖模型隱藏費率和 QA 信息。 我以為我可以通過為RateQA屬性分配一個null來做到這一點,但它似乎不起作用: Distinct工作不正確。 我換了之后
費率 = showRateAndQA ? new QA { Grade = x.QA.Grade ... } : 空,Rate = new QA { Grade = showRateAndQA ? x.QA.Grade : null ... },

Distinct工作正常。

顯然 EF 不喜歡我將null分配給我的 lambda 中的對象。

從內存中,默認的Distinct()實現通過對相應類使用默認的Equals()方法來工作,這通常是不需要的(我發現至少我的工作就是這種情況)。

您需要進行如下設置;

public class ProvidersViewModel : IEqualityComparer<ProvidersViewModel>
{
    public bool Equals(ProvidersViewModel x, ProvidersViewModel y)
    {
        if (x.col1 == y.col1 && x.col2 == y.col2 && x.col3 == y.col3)
            return true;
        else
            return false;
    }

    public int GetHashCode(ProvidersViewModel obj)
    {
        int hCode = obj.col1 ^ obj.col2 ^ obj.col3;
        return hCode.GetHashCode();
    }

    // Existing code, fields, etc.
}

這應該允許對Distinct()的調用正常工作。

暫無
暫無

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

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