在有人跳到重复标记之前,我已经看过了,每个人都在做比我尝试的要复杂的事情。
因此,我正在处理一个要检查大量数据的数据库,而将LINQ的Any()扩展转换为SQL的速度不如SQL的Count(1)> 0快,所以我在写的所有地方:< / p>
var someBool = Ctx.SomeEntities.Count(x => x.RelatedEntity.Count(y => y.SomeProperty == SomeValue) > 0) > 0;
在Pseudo中:我的任何实体是否与某个其他属性具有SomeValue值的属性有关系。
这很好用,而且很快。但是,它不是完全可读的(而且我有很多东西,比情况下嵌入的更多),所以我想做的是将其替换为:
var someBool = Ctx.SomeEntities.AnyX(x => x.RelatedEntity.AnyX(y => y.SomeProperty == SomeValue));
具有:
public static bool AnyX<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) => source.Count(predicate) > 0;
因此,您看到我没有执行LINQ无法转换为SQL的任何操作,我没有执行LINQ尚未转换为SQL的任何操作,而只是通过创建一个额外的扩展,我得到了:
LINQ to Entities无法识别方法布尔型AnyX等...
一定有某种编写扩展程序的方式或某种告诉LINQ的方式,只是为了看一下代码,您就会发现可以做到这一点。
答案 0 :(得分:0)
不是您的特定问题的答案,但我建议您重新考虑如何处理查询。
让我们使用一些易于理解的描述性名称:是否有任何家庭的居民姓“ Bobby”?
// your way
Ctx.Households.Count( hh => hh.Residents.Count( r => r.FirstName == "Bobby" ) > 0 ) > 0
糟糕,倒退了。从居民开始:
Ctx.Residents.Count( r =>
r.FirstName == "Bobby"
&& r.Household != null ) // if needed
> 0;
现在,生成的SQL是否会与以下代码明显不同?
Ctx.Residents.Any( r => r.FirstName == "Bobby" && r.Household != null)
编辑:
这是一个真实的MCVE,其结果与您的结论相反:
/*
create table TestDatum
(
TestValue nchar(36) not null
)
*/
/*
set nocount on
declare @count int
declare @start datetime
declare @end datetime
set @count = 0
set @start = GETDATE()
while @count < 14000000
begin
insert TestDatum values( CONVERT(nchar(36), NEWID()) )
set @count = @count + 1
if (@count % 100000) = 0
begin
print convert(nvarchar, @count)
end
end
set @end = GETDATE()
select CONVERT(nvarchar, DATEDIFF(ms, @start, @end))
*/
/*
-- "Any" test
declare @startdt datetime, @enddt datetime
set @startdt = GETDATE()
DECLARE @p0 NVarChar(1000) = '%abcdef%'
SELECT
(CASE
WHEN EXISTS(
SELECT NULL AS [EMPTY]
FROM TestDatum AS [t0]
WHERE [t0].TestValue LIKE @p0
) THEN 1
ELSE 0
END) AS [value]
set @enddt = GETDATE()
select DATEDIFF(ms, @startdt, @enddt) -- ~7000ms
*/
/*
-- "Count" test
declare @startdt datetime, @enddt datetime
set @startdt = GETDATE()
-- Region Parameters
DECLARE @p0 NVarChar(1000) = '%abcdef%'
-- EndRegion
SELECT COUNT(*) AS [value]
FROM TestDatum AS [t0]
WHERE [t0].TestValue LIKE @p0
set @enddt = GETDATE()
select DATEDIFF(ms, @startdt, @enddt) -- > 48000ms
*/