LinqKitEFCore.Extension.AutoBuildPredicate 0.1.4

There is a newer version of this package available.
See the version list below for details.
dotnet add package LinqKitEFCore.Extension.AutoBuildPredicate --version 0.1.4
NuGet\Install-Package LinqKitEFCore.Extension.AutoBuildPredicate -Version 0.1.4
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LinqKitEFCore.Extension.AutoBuildPredicate" Version="0.1.4" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add LinqKitEFCore.Extension.AutoBuildPredicate --version 0.1.4
#r "nuget: LinqKitEFCore.Extension.AutoBuildPredicate, 0.1.4"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install LinqKitEFCore.Extension.AutoBuildPredicate as a Cake Addin
#addin nuget:?package=LinqKitEFCore.Extension.AutoBuildPredicate&version=0.1.4

// Install LinqKitEFCore.Extension.AutoBuildPredicate as a Cake Tool
#tool nuget:?package=LinqKitEFCore.Extension.AutoBuildPredicate&version=0.1.4

LinqKitEFCore.Extension.AutoBuildPredicate

This .NET core extension is free and easy to use to search entities much easier, without null checking and building big expression trees.

Library contains:

  • SearchPredicateEngine,
  • Attributes,
  • Custom model classes

How it works?

To use, you just have to instantiate the engine:


var predicateEngine = new PredicateEngine<TEntity>();

var myExpressionStarter = predicateEngine.PredicateByFilter(filterModel)

IQueryable<YourReturnType> = context.TEntity.Where(myExpressionStarter);

Before doing it you have to define class "filterModel"

The simplest way is just put properties with the same names as in an entity class. It is important that all properties are nullable types, otherwise if you have integer property and you does not initialize, the library will add an expression to predicate where property equals to zero. In filter class you can use all Built-in types, for DateTime you have to use library class "DateTimeFromToFilter"

Example:

EntityClass

   public class Product
    {
        public int ProductID { get; set; }
        public string ProductCategory { get; set; }
        public decimal ProductPrice { get; set; }
        public double ProductWeight { get; set; }
        public int Units { get; set; }
    }

FilterClass

   public class ProductFilter
    {
        public int? ProductID { get; set; }
        public string ProductCategory { get; set; }
        public decimal? ProductPrice { get; set; }
        public double? ProductWeight { get; set; }
        public int? Units { get; set; }
    }

If you pass empty filter, it will return all objects in entity of type Product. Providing the property value will be compared to the entity property by operator "==" for primitives and "Equals" for string.

Of course you can pass anonymous class instead of creating filterClass but I strongly adviste to use it to a small number of filtering properties.

</br>

Extend filter class by built-in "Custom model classes" and "Custom attributes"

Custom model classes:

  • StringFilter

    With StringFilter you can pass StringSearchOption(Equals, Contains, StartsWith, EndsWith), where default value is "Equals" and StringComparison where default value is none

  • NumericFilter

    With NumericFilter you can pass generic Value1 (Required) or/and generic Value2 and set CompareExpressionType(Equal, GreaterThan...). This values have to be nullable type!

  • DateTimeFromToFilter

    With DateTimeFromToFilter you can pass DateFrom (Required) or/and DateTo and set CompareExpressionType(Equal, GreaterThan...).

  • CollectionFilter

    This class accepts generic List, it is used to build predicate :

    entity => Collection.Contains(entity.Property) 
    

Custom attributes:

  • EntityPropertyName

    This attribute overrides filter class property name if you can't use explicitly same name as in entity class.

  • CustomSearchPath

    In this attribute you can pass a nested searchPath, but only for one-to-one entities. This option require to pass AssemblyName and TypeName of nested entity to CustomSearchPathAttribute or by constructor of PredicateEngine:

   var predicateEngine = new PredicateEngine<TEntity>("myAssemblyName", "myTypeName");

AssemblyName and TypeName setted by CustomSearchPathAttribute will always be overriden by passing them via constructor but only for that property where attribute was set.

  • NotThisEntityProperty
    This attribute is used when in filter class want to use property which is not a member of entity passed to engine. You can use it when path to that property is complicated so you can't use CustomSearchPath. Then you can define expression like this:
var myExpressionStarter = predicateEngine.PredicateByFilter(filterModel);
myExpressionStarter = myExpressionStarter.And(entity=>entity.<yourCustomExpr>)
  • PredicateBitwiseOperation
    This attribute sets the bitwise operation for predicate builder. By using it you can define how each property will be combined in predicate. And and Or shall be construed respectively as AndALso and OrElse bitwise operators. Default value is set to And.

Examples with custom utilities

#1 Example

   public class Product
    {
        public int ProductID { get; set; }
        public string ProductCategory { get; set; }
        public decimal ProductPrice { get; set; }
        public double ProductWeight { get; set; }
        public int Units { get; set; }
        public DateTime PackingDay {get;set;}
    }
 public class ProductFilter
    {
        public NumericFilter<int?> ProductID { get; set; }
        public StringFilter ProductCategory { get; set; }
        public NumericFilter<decimal?> ProductPrice { get; set; }
        public NumericFilter<double?> ProductWeight { get; set; }
        public int? Units { get; set; }
        public DateTimeFromToFilter PackingDay { get; set; }
     }
JSON for ProductFilter
{
   "productID":{
      "value1":{
         "value":120,
         "expressionType":"GreaterThanOrEqual"
      },
      "value2":{
         "value":180,
         "expressionType":"LessThanOrEqual"
      }
   },
   "productCategory":{
      "str":"toy",
      "stringSearchOption":"Contains",
      "stringComparison":"InvariantCultureIgnoreCase"
   },
   "productPrice":{
      "value1":{
         "value":250,
         "expressionType":"Equal"
      },
      "value2":{
         "value":287,
         "expressionType":"Equal"
      }
   },
   "productWeight":{
      "value1":{
         "value":500,
         "expressionType":"GreaterThanOrEqual"
      }
   },
   "Units":20,
   "packingDay":{
      "dateFrom":{
         "dateTime":"2019-10-25T09:00:00",
         "expressionType":"GreaterThanOrEqual"
      },
      "dateTo":{
         "dateTime":"2019-10-25T15:00:00",
         "expressionType":"LessThanOrEqual"
      },
      "truncateTime":"false"
   }
}
It is equivalent to
{
	entity => (

			(
				(
					(		
						(
							((entity.ProductID >= 120) Or (entity.ProductID <= 180)) 
									
							AndAlso entity.ProductCategory.Contains("toy", InvariantCultureIgnoreCase)
						) 
						AndAlso ((entity.ProductPrice == 250) Or (entity.ProductPrice == 287))
					) 
					AndAlso (entity.ProductWeight >= 500)
				) 
			    AndAlso (entity.Units == 20)
			) 
		    AndAlso ((entity.PackingDay >= 25.10.2019 09:00:00) AndAlso (entity.PackingDay <= 25.10.2019 15:00:00))
	)
}

More examples with attributes coming soon.

This is my first public code as nupkg, so I am fully open to any suggestions and changes 😃

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.2 is compatible.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.5.18 7,599 7/13/2021
0.5.17 352 7/13/2021
0.5.16 361 7/13/2021
0.5.15 363 7/13/2021
0.5.14 601 3/23/2021
0.5.13 369 2/9/2021
0.3.0 566 4/20/2020
0.2.9 456 3/19/2020
0.2.8 485 3/19/2020
0.2.7 499 3/19/2020
0.2.6 495 3/19/2020
0.2.5 486 3/19/2020
0.2.4 482 3/19/2020
0.2.3 468 3/19/2020
0.2.2 494 3/19/2020
0.2.1 469 3/19/2020
0.2.0 534 12/20/2019
0.1.6 494 11/20/2019
0.1.5 504 10/30/2019
0.1.4 483 10/29/2019
0.1.3 518 10/29/2019
0.1.2 530 10/29/2019
0.1.0-beta 370 10/29/2019