Linq All on empty collection

jlp*_*jlp 15 .net c# linq entity-framework

我需要检查所有定义是否包含一些特定数据.除了GroupBy返回空集合的情况外,它工作正常.

var exist = dbContext.Definitions
                     .Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId)
                     .GroupBy(x => x.PropertyTypeId)
                     .All(...some condition...);
Run Code Online (Sandbox Code Playgroud)

如何重写这样所有All将在空集合上返回false?

更新:这是一个LINQ to SQL,我想在单个调用中执行它.

更新2:我认为这有效:

var exist = dbContext.Definitions
                     .Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId)
                     .GroupBy(x => x.PropertyTypeId)
                     .Count(x => x
                        .All(...some condition...)) == propertyTypeIds.Count;
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 13

如果你正在使用LINQ to Objects,我只想编写自己的扩展方法.我的Edulinq项目有示例代码All,并且非常简单:

public static bool AnyAndAll<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate)
{
    if (source == null)
    {
        throw new ArgumentNullException(nameof(source));
    }
    if (predicate == null)
    {
        throw new ArgumentNullException(nameof(predicate));
    }

    bool any = false;
    foreach (TSource item in source)
    {
        any = true;
        if (!predicate(item))
        {
            return false;
        }
    }
    return any;
}
Run Code Online (Sandbox Code Playgroud)

这避免了多次评估输入.


Dam*_*ver 5

您可以使用以下方式执行此操作Aggregate:

.Aggregate(new {exists = 0, matches = 0}, (a, g) =>
        new {exists = a.exists + 1, matches = a.matches + g > 10 ? 1 : 0})
Run Code Online (Sandbox Code Playgroud)

(这g > 10是我的测试)

然后exists是大于零existsmatches具有相同值的简单逻辑.

这样可以避免两次运行整个查询.


naw*_*fal 5

您可以使用DefaultIfEmpty扩展方法,并调整您的some condition使其评估nullfalse.

var exist = definitions
    .Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId)
    .GroupBy(x => x.PropertyTypeId)
    .DefaultIfEmpty()
    .All(...some condition...));
Run Code Online (Sandbox Code Playgroud)


Adi*_*dov 0

编写自己的扩展方法怎么样?(我很确定你会命名得更好)

public static bool NotEmptyAll<T>(
    this IEnumerable<T> collection, 
    Func<T, bool> predicate)
{
    return collection != null
        && collection.Any()
        && collection.All(predicate);
}
Run Code Online (Sandbox Code Playgroud)

然后调用它而不是All

var exist = definitions.Where(
        x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId)
         .GroupBy(x => x.PropertyTypeId)
         .NotEmptyAll(
             ...some condition...));
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这会执行查询两次,这很可能是一个坏主意。 (5认同)