[英]EF Distinct on IQueryable doesn't remove duplicates
I have a generic class that is supposed to filter, order, project and paginate an IQueryable
by calling this method:我有一个通用类,它应该通过调用此方法来过滤、排序、投影和分页
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;
}
I am calling Distinct()
here我在这里调用
Distinct()
var projected = filtered
.Select(converter)
.Distinct();
to remove any duplicates that may appear after projection.删除投影后可能出现的任何重复项。
My assumption was that EF6 would generate something like我的假设是 EF6 会产生类似
SELECT DISTINCT Col1, Col2, Col3 FROM (SELECT Col1, Col2, Col3, Col4 FROM SOME_TABLE WHERE <some conditions on co1, col2, col3, col4 ...>)
ie that it would apply DISTINCT
to the projection, so, if there are two rows with same col1, col2, col3 but different col4, only one row would make it into the result.即它会将
DISTINCT
应用于投影,因此,如果有两行具有相同的 col1、col2、col3 但 col4 不同,则只有一行会使其成为结果。 However, the SQL that I get looks like this:但是,我得到的 SQL 如下所示:
SELECT Col1, Col2, Col3, Col4 FROM (SELECT DISTINCT Col1, Col2, Col3, Col4 FROM SOME_TABLE)
- no projection, and DISTINCT is shifted into a subquery, as if I were doing this: - 没有投影,并且 DISTINCT 被转移到子查询中,就好像我在这样做:
var projected = filtered
.Distinct()
.Select(converter)
I want this service to be a generic, ie potentially working with any TSource
and TResult
, but looks like there's some pitfall here and my understanding of what EF does is not correct.我希望这个服务是通用的,即可能与任何
TSource
和TResult
一起工作,但看起来这里有一些陷阱,我对 EF 所做的事情的理解是不正确的。
What's going on here?这里发生了什么?
UPDATE更新
I believe the problem is in my converter.我相信问题出在我的转换器上。 I used the following function to generate the lambda expression passed to
Select
:我使用以下函数生成传递给
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
is a join of providers, their rates and QAs. ProviderJoinRateAndQA
是提供者、他们的费率和 QA 的连接。 Each Provider
can have multiple services, rates and qas.每个
Provider
可以有多种服务、费率和质量保证。 In some cases I want view model to hide the rate and QA info.在某些情况下,我希望视图模型隐藏费率和 QA 信息。 I assumed I could do it by assigning a
null
to Rate
and QA
properties, but it doesn't seem to work: Distinct
works incorrectly.我以为我可以通过为
Rate
和QA
属性分配一个null
来做到这一点,但它似乎不起作用: Distinct
工作不正确。 After I replaced我换了之后
Rate = showRateAndQA ?费率 = showRateAndQA ? new QA { Grade = x.QA.Grade ... } : null with Rate = new QA { Grade = showRateAndQA ?
new QA { Grade = x.QA.Grade ... } : 空,Rate = new QA { Grade = showRateAndQA ? x.QA.Grade : null ... },
x.QA.Grade : null ... },
Distinct
worked correctly. Distinct
工作正常。
Apparently EF didn't like my assigning null
to object in my lambda.显然 EF 不喜欢我将
null
分配给我的 lambda 中的对象。
From memory, the default Distinct()
implementation works by using the default Equals()
method for the respective class, which is often unwanted (I've found this to be the case with my work atleast).从内存中,默认的
Distinct()
实现通过对相应类使用默认的Equals()
方法来工作,这通常是不需要的(我发现至少我的工作就是这种情况)。
You need to set up something like the following;您需要进行如下设置;
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.
}
This should then allow the call to Distinct()
to work properly.这应该允许对
Distinct()
的调用正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.