< Summary - ZhEaIsNsAaBn.Libraries coverage (affected: 23 packages)

Information
Class: Microsoft.EntityFrameworkCore.QueryableExtensions
Assembly: ZhEaIsNsAaBn.Infrastructure.Core
File(s): /home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.Core/Extensions/QueryableExtensions.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 44
Coverable lines: 44
Total lines: 177
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 28
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
FilterIfAny(...)0%2040%
FilterIfAny(...)0%4260%
FilterAnyOrNone(...)0%4260%
FilterIfAnyContains(...)0%620%
WhereEquals(...)0%620%
WhereIn(...)0%2040%
Property(...)0%2040%

File(s)

/home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.Core/Extensions/QueryableExtensions.cs

#LineLine coverage
 1using System.Collections;
 2using System.Reflection;
 3using LinqKit;
 4
 5// ReSharper disable once CheckNamespace
 6namespace Microsoft.EntityFrameworkCore;
 7
 8/// <summary>Optional-filter helpers for <see cref="IQueryable{T}"/>: a filter is skipped when its value is empty.</summ
 9public static class QueryableExtensions
 10{
 011    private static readonly MethodInfo _stringContains = typeof( string ).GetMethod( nameof( string.Contains ), [ typeof
 12
 013    private static readonly MethodInfo _enumerableContains = typeof( Enumerable ).GetMethods()
 014                                                                                 .First( m => m.Name == nameof( Enumerab
 15
 16
 17    /// <summary>Keeps rows whose <paramref name="selector"/> value is in <paramref name="values"/>; no filter when <par
 18    /// <typeparam name="TEntity">The row type.</typeparam>
 19    /// <typeparam name="TValue">The value type.</typeparam>
 20    /// <param name="source">The query.</param>
 21    /// <param name="values">The allowed values.</param>
 22    /// <param name="selector">The property to test.</param>
 23    /// <returns>The filtered query.</returns>
 24    public static IQueryable<TEntity> FilterIfAny< TEntity, TValue >( this IQueryable<TEntity> source, ICollection<TValu
 25    {
 026        ArgumentNullException.ThrowIfNull( selector );
 27
 028        if ( values is not { Count: > 0 } ) { return source; }
 29
 30
 031        var contains = Expression.Call( Expression.Constant( values ), typeof( ICollection<TValue> ).GetMethod( nameof( 
 32
 33
 034        return source.Where( Expression.Lambda<Func<TEntity, bool>>( contains, selector.Parameters ) );
 35    }
 36
 37    /// <summary>Keeps rows whose <paramref name="selector"/> value equals <paramref name="value"/>; no filter when it i
 38    /// <typeparam name="TEntity">The row type.</typeparam>
 39    /// <typeparam name="TValue">The value type.</typeparam>
 40    /// <param name="source">The query.</param>
 41    /// <param name="value">The value.</param>
 42    /// <param name="selector">The property to test.</param>
 43    /// <returns>The filtered query.</returns>
 44    public static IQueryable<TEntity> FilterIfAny< TEntity, TValue >( this IQueryable<TEntity> source, TValue? value, Ex
 45    {
 046        ArgumentNullException.ThrowIfNull( selector );
 47
 048        if ( value is null || value is string text && string.IsNullOrWhiteSpace( text ) ) { return source; }
 49
 50
 051        var equal = Expression.Equal( selector.Body, Expression.Constant( value, typeof( TValue ) ) );
 52
 53
 054        return source.Where( Expression.Lambda<Func<TEntity, bool>>( equal, selector.Parameters ) );
 55    }
 56
 57    /// <summary>
 58    /// Keeps rows where any mapped request value (that isn't blank) equals its column (OR). When every value is blank,
 59    /// no rows are returned.
 60    /// </summary>
 61    /// <typeparam name="TEntity">The row type.</typeparam>
 62    /// <typeparam name="TRequest">The request type.</typeparam>
 63    /// <param name="query">The query.</param>
 64    /// <param name="request">The request holding the values.</param>
 65    /// <param name="mappings">Pairs of request value getter and column selector.</param>
 66    /// <returns>The filtered query.</returns>
 67    public static IQueryable<TEntity> FilterAnyOrNone< TEntity, TRequest >(
 68            this IQueryable<TEntity> query, TRequest request,
 69            IEnumerable<(Func<TRequest, string> getValue, Expression<Func<TEntity, string>> selector)> mappings
 70        )
 71    {
 072        ArgumentNullException.ThrowIfNull( mappings );
 73
 074        var conditions = new List<Expression<Func<TEntity, bool>>>();
 75
 76
 077        foreach ( var (getValue, selector) in mappings )
 78        {
 079            var value = getValue( request );
 80
 081            if ( string.IsNullOrWhiteSpace( value ) ) { continue; }
 82
 83
 084            conditions.Add( Expression.Lambda<Func<TEntity, bool>>( Expression.Equal( selector.Body, Expression.Constant
 85        }
 86
 87
 088        if ( conditions.Count == 0 ) { return query.Where( _ => false ); }
 89
 90
 091        Expression<Func<TEntity, bool>> none = PredicateBuilder.New<TEntity>( false );
 92
 93
 094        return query.Where( conditions.Aggregate( none, ( predicate, condition ) => predicate.Or( condition ) ) );
 95    }
 96
 97    /// <summary>Keeps rows whose text <paramref name="selector"/> contains <paramref name="value"/>; no filter when it 
 98    /// <typeparam name="TEntity">The row type.</typeparam>
 99    /// <typeparam name="TValue">The selected type (text).</typeparam>
 100    /// <param name="source">The query.</param>
 101    /// <param name="value">The text to look for.</param>
 102    /// <param name="selector">The text property.</param>
 103    /// <returns>The filtered query.</returns>
 104    public static IQueryable<TEntity> FilterIfAnyContains< TEntity, TValue >( this IQueryable<TEntity> source, string? v
 105    {
 0106        ArgumentNullException.ThrowIfNull( selector );
 107
 0108        if ( string.IsNullOrWhiteSpace( value ) ) { return source; }
 109
 110
 0111        var contains = Expression.Call( selector.Body, _stringContains, Expression.Constant( value ) );
 112
 113
 0114        return source.Where( Expression.Lambda<Func<TEntity, bool>>( contains, selector.Parameters ) );
 115    }
 116
 117    /// <summary>Keeps rows whose property <paramref name="propertyName"/> equals <paramref name="value"/> (nullable pro
 118    /// <typeparam name="T">The row type.</typeparam>
 119    /// <param name="source">The query.</param>
 120    /// <param name="propertyName">The property name.</param>
 121    /// <param name="value">The value, converted to the property type.</param>
 122    /// <returns>The filtered query.</returns>
 123    /// <exception cref="ArgumentException"><typeparamref name="T"/> has no property <paramref name="propertyName"/>.</e
 124    public static IQueryable<T> WhereEquals< T >( this IQueryable<T> source, string propertyName, object value )
 125    {
 0126        var (parameter, property, valueType, isNullable) = Property<T>( propertyName );
 0127        var constant                                      = Expression.Constant( Convert.ChangeType( value, valueType, C
 128
 129
 0130        Expression body = isNullable
 0131                              ? Expression.AndAlso( Expression.Property( property, "HasValue" ), Expression.Equal( Expre
 0132                              : Expression.Equal( property, constant );
 133
 134
 0135        return source.Where( Expression.Lambda<Func<T, bool>>( body, parameter ) );
 136    }
 137
 138    /// <summary>Keeps rows whose property <paramref name="propertyName"/> is one of <paramref name="values"/>.</summary
 139    /// <typeparam name="T">The row type.</typeparam>
 140    /// <param name="source">The query.</param>
 141    /// <param name="propertyName">The property name.</param>
 142    /// <param name="values">The values, converted to the property type.</param>
 143    /// <returns>The filtered query.</returns>
 144    /// <exception cref="ArgumentNullException"><paramref name="values"/> is <see langword="null"/>.</exception>
 145    /// <exception cref="ArgumentException"><typeparamref name="T"/> has no property <paramref name="propertyName"/>.</e
 146    public static IQueryable<T> WhereIn< T >( this IQueryable<T> source, string propertyName, IEnumerable<object> values
 147    {
 0148        ArgumentNullException.ThrowIfNull( values );
 149
 0150        var (parameter, property, valueType, isNullable) = Property<T>( propertyName );
 0151        var typedValues                                   = (IList) Activator.CreateInstance( typeof( List<> ).MakeGener
 152
 153
 0154        foreach ( var item in values ) { typedValues.Add( Convert.ChangeType( item, valueType, CultureInfo.InvariantCult
 155
 156
 0157        var        contains = _enumerableContains.MakeGenericMethod( valueType );
 0158        var        list     = Expression.Constant( typedValues );
 0159        Expression body     = isNullable
 0160                                  ? Expression.AndAlso( Expression.Property( property, "HasValue" ), Expression.Call( co
 0161                                  : Expression.Call( contains, list, property );
 162
 163
 0164        return source.Where( Expression.Lambda<Func<T, bool>>( body, parameter ) );
 165    }
 166
 167
 168    private static (ParameterExpression Parameter, MemberExpression Property, Type ValueType, bool IsNullable) Property<
 169    {
 0170        var propertyInfo = typeof( T ).GetProperty( propertyName ) ?? throw new ArgumentException( $"Property '{property
 0171        var parameter    = Expression.Parameter( typeof( T ), "x" );
 0172        var underlying   = Nullable.GetUnderlyingType( propertyInfo.PropertyType );
 173
 174
 0175        return ( parameter, Expression.Property( parameter, propertyInfo ), underlying ?? propertyInfo.PropertyType, und
 176    }
 177}