{"id":580,"date":"2020-08-14T09:20:00","date_gmt":"2020-08-13T20:20:00","guid":{"rendered":"https:\/\/blog.wiseowls.co.nz\/?p=580"},"modified":"2026-03-08T00:44:48","modified_gmt":"2026-03-07T11:44:48","slug":"entity-framework-core-3-1-dynamic-where-clause","status":"publish","type":"post","link":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/","title":{"rendered":"Entity Framework Core 3.1 \u2013 dynamic WHERE clause"},"content":{"rendered":"\n<p>Every now and then we get tasked with building a backend for filtering arbitrary queries. Usually clients would like to have a method of sending over an array of fields, values, and comparisons operations in order to retrieve their data. For simplicity we&#8217;ll assume that all conditions are joining each other with an <code>AND<\/code> operator.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">public class QueryableFilter {\n    public string Name { get; set; }\n    public string Value { get; set; }\n    public QueryableFilterCompareEnum? Compare { get; set; }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">With a twist<\/h2>\n\n\n\n<p>There&#8217;s however one slight complication to this problem &#8211; filters must apply to fields on dependent entities (possible multiple levels of nesting as well). This can become a problem not only because we&#8217;d have to traverse model hierarchy (we&#8217;ll touch on that later), but also because of ambiguity this requirement introduces. Sometimes we&#8217;re lucky to only have unique column names across the hierarchy. However more often than not this needs to be resolved one way or another. We can, for example, require filter fields to use dot notation so we know which entity each field relates to. For example, <code>Name<\/code> <code>-eq \"ACME Ltd\" AND Name<\/code> <code>-eq \"Cloud Solutions\"<\/code> becomes <code>company.Name -eq \"ACME Ltd\" AND team.Name<\/code> <code>-eq \"Cloud Solutions\"<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Building an expression<\/h2>\n\n\n\n<p>It is pretty common that clients already have some sort of data querying service with <a href=\"https:\/\/github.com\/dotnet\/efcore\" target=\"_blank\" rel=\"noreferrer noopener\">EF Core<\/a> doing the actual database comms. And since EF relies on LINQ Expressions a lot &#8211; we can build required filters dynamically.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">public static IQueryable&lt;T> BuildExpression&lt;T>(this IQueryable&lt;T> source, DbContext context, string columnName, string value, QueryableFilterCompareEnum? compare = QueryableFilterCompareEnum.Equal)\n{\n\tvar param = Expression.Parameter(typeof(T));\n\n\t\/\/ Get the field\/column from the Entity that matches the supplied columnName value\n\t\/\/ If the field\/column does not exists on the Entity, throw an exception; There is nothing more that can be done\n\tMemberExpression dataField;\n\t\n\tvar model = context.Model.FindEntityType(typeof(T)); \/\/ start with our own entity\n\tvar props = model.GetPropertyAccessors(param); \/\/ get all available field names including navigations\n\tvar reference = props.First(p => RelationalPropertyExtensions.GetColumnName(p.Item1) == columnName); \/\/ find the filtered column - you might need to handle cases where column does not exist\n\n\tdataField = reference.Item2 as MemberExpression; \/\/ we happen to already have correct property accessors in our Tuples\t\n\n\tConstantExpression constant = !string.IsNullOrWhiteSpace(value)\n\t\t? Expression.Constant(value.Trim(), typeof(string))\n\t\t: Expression.Constant(value, typeof(string));\n\n\tBinaryExpression binary = GetBinaryExpression(dataField, constant, compare);\n\tExpression&lt;Func&lt;T, bool>> lambda = (Expression&lt;Func&lt;T, bool>>)Expression.Lambda(binary, param);\n\treturn source.Where(lambda);\n}<\/code><\/pre>\n\n\n\n<p>Most of the code above is pretty standard for building property accessor lambdas, but <code>GetPropertyAccessors<\/code> is the key:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">private static IEnumerable&lt;Tuple&lt;IProperty, Expression>> GetPropertyAccessors(this IEntityType model, Expression param)\n{\n\tvar result = new List&lt;Tuple&lt;IProperty, Expression>>();\n\n\tresult.AddRange(model.GetProperties()\n\t\t\t\t\t\t\t\t.Where(p => !p.IsShadowProperty()) \/\/ this is your chance to ensure property is actually declared on the type before you attempt building Expression\n\t\t\t\t\t\t\t\t.Select(p => new Tuple&lt;IProperty, Expression>(p, Expression.Property(param, p.Name)))); \/\/ Tuple is a bit clunky but hopefully conveys the idea\n\n\tforeach (var nav in model.GetNavigations().Where(p => p is Navigation))\n\t{\n\t\tvar parentAccessor = Expression.Property(param, nav.Name); \/\/ define a starting point so following properties would hang off there\n\t\tresult.AddRange(GetPropertyAccessors(nav.ForeignKey.PrincipalEntityType, parentAccessor)); \/\/recursively call ourselves to travel up the navigation hierarchy\n\t}\n\n\treturn result;\n}<\/code><\/pre>\n\n\n\n<p>this is where we interrogate EF as-built data model, traverse navigation properties and recursively build a list of all properties we can ever filter on!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing it out<\/h2>\n\n\n\n<p>Talk is cheap, let&#8217;s run a complete example here:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">public class Entity\n{\n\tpublic int Id { get; set; }\n}\nclass Company : Entity\n{\n\tpublic string CompanyName { get; set; }\n}\n\nclass Team : Entity\n{\n\tpublic string TeamName { get; set; }\n\tpublic Company Company { get; set; }\n}\n\nclass Employee : Entity\n{\n\tpublic string EmployeeName { get; set; }\n\tpublic Team Team { get; set; }\n}\n\nclass DynamicFilters&lt;T> where T : Entity\n{\n\tprivate readonly DbContext _context;\n\n\tpublic DynamicFilters(DbContext context)\n\t{\n\t\t_context = context;\n\t}\n\n\tpublic IEnumerable&lt;T> Filter(IEnumerable&lt;QueryableFilter> queryableFilters = null)\n\t{\n\t\tIQueryable&lt;T> mainQuery = _context.Set&lt;T>().AsQueryable().AsNoTracking();\n\t\t\/\/ Loop through the supplied queryable filters (if any) to construct a dynamic LINQ-to-SQL queryable\n\t\tforeach (var filter in queryableFilters ?? new List&lt;QueryableFilter>())\n\t\t{\n\t\t\tmainQuery = mainQuery.BuildExpression(_context, filter.Name, filter.Value, filter.Compare);\n\t\t}\n\n\t\tmainQuery = mainQuery.OrderBy(x => x.Id);\n\n\t\treturn mainQuery.ToList();\n\t}\n}\n\/\/ --- DbContext\nclass MyDbContext : DbContext\n{\n\tpublic DbSet&lt;Company> Companies { get; set; }\n\tpublic DbSet&lt;Team> Teams { get; set; }\n\tpublic DbSet&lt;Employee> Employees { get; set; }\n\n\tprotected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n\t{\n\t\toptionsBuilder.UseSqlServer(\"Server=.\\\\SQLEXPRESS;Database=test;Trusted_Connection=true\");\n\t\tbase.OnConfiguring(optionsBuilder);\n\t}\n}\n\/\/ ---\nstatic void Main(string[] args)\n{\n\tvar context = new MyDbContext();\n\tvar someTableData = new DynamicFilters&lt;Employee>(context).Filter(new\n\tList&lt;QueryableFilter> { new QueryableFilter { Name = \"CompanyName\", Value = \"ACME Ltd\" }, new QueryableFilter { Name = \"TeamName\", Value = \"Cloud Solutions\" } });\n}<\/code><\/pre>\n\n\n\n<p>The above block <a href=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/07\/06\/entity-framework-core-3-1-peeking-into-generated-sql\/\">should produce<\/a> following SQL:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"sql\" class=\"language-sql\">SELECT [e].[Id], [e].[EmployeeName], [e].[TeamId]\nFROM [Employees] AS [e]\nLEFT JOIN [Teams] AS [t] ON [e].[TeamId] = [t].[Id]\nLEFT JOIN [Companies] AS [c] ON [t].[CompanyId] = [c].[Id]\nWHERE [c].[CompanyName] = N'ACME Ltd'\n AND [t].[TeamName] = N'Cloud Solutions'\nORDER BY [e].[Id]<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Every now and then we get tasked with building a backend for filtering arbitrary queries. Usually clients would like to have a method of sending over an array of fields, values, and comparisons operations in order to retrieve their data. For simplicity we&#8217;ll assume that all conditions are joining each other with an AND operator. &hellip; <a href=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Entity Framework Core 3.1 \u2013 dynamic WHERE clause&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":391,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[11],"tags":[23,59],"class_list":["post-580","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev","tag-ef-core","tag-sql"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Entity Framework Core 3.1 \u2013 dynamic WHERE clause - Timur and associates<\/title>\n<meta name=\"description\" content=\"Building dynamic WHERE clauses in EF Core 3.1 with expression trees. Supports nested properties and multiple comparison operators.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Entity Framework Core 3.1 \u2013 dynamic WHERE clause - Timur and associates\" \/>\n<meta property=\"og:description\" content=\"Building dynamic WHERE clauses in EF Core 3.1 with expression trees. Supports nested properties and multiple comparison operators.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/\" \/>\n<meta property=\"og:site_name\" content=\"Timur and associates\" \/>\n<meta property=\"article:published_time\" content=\"2020-08-13T20:20:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-07T11:44:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1980\" \/>\n\t<meta property=\"og:image:height\" content=\"801\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"timur\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@TimurKh\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/\"},\"author\":{\"name\":\"timur\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#\\\/schema\\\/person\\\/34d0ed30d573b5bc317ea990bd2e0c59\"},\"headline\":\"Entity Framework Core 3.1 \u2013 dynamic WHERE clause\",\"datePublished\":\"2020-08-13T20:20:00+00:00\",\"dateModified\":\"2026-03-07T11:44:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/\"},\"wordCount\":265,\"commentCount\":1,\"image\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg\",\"keywords\":[\"ef-core\",\"sql\"],\"articleSection\":[\"Development\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/\",\"url\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/\",\"name\":\"Entity Framework Core 3.1 \u2013 dynamic WHERE clause - Timur and associates\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg\",\"datePublished\":\"2020-08-13T20:20:00+00:00\",\"dateModified\":\"2026-03-07T11:44:48+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#\\\/schema\\\/person\\\/34d0ed30d573b5bc317ea990bd2e0c59\"},\"description\":\"Building dynamic WHERE clauses in EF Core 3.1 with expression trees. Supports nested properties and multiple comparison operators.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/#primaryimage\",\"url\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg\",\"contentUrl\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg\",\"width\":1980,\"height\":801},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/index.php\\\/2020\\\/08\\\/14\\\/entity-framework-core-3-1-dynamic-where-clause\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Entity Framework Core 3.1 \u2013 dynamic WHERE clause\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#website\",\"url\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/\",\"name\":\"Timur and associates\",\"description\":\"Notes of an IT contractor\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blog.wiseowls.co.nz\\\/#\\\/schema\\\/person\\\/34d0ed30d573b5bc317ea990bd2e0c59\",\"name\":\"timur\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg\",\"caption\":\"timur\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/TimurKh\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Entity Framework Core 3.1 \u2013 dynamic WHERE clause - Timur and associates","description":"Building dynamic WHERE clauses in EF Core 3.1 with expression trees. Supports nested properties and multiple comparison operators.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/","og_locale":"en_US","og_type":"article","og_title":"Entity Framework Core 3.1 \u2013 dynamic WHERE clause - Timur and associates","og_description":"Building dynamic WHERE clauses in EF Core 3.1 with expression trees. Supports nested properties and multiple comparison operators.","og_url":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/","og_site_name":"Timur and associates","article_published_time":"2020-08-13T20:20:00+00:00","article_modified_time":"2026-03-07T11:44:48+00:00","og_image":[{"width":1980,"height":801,"url":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg","type":"image\/jpeg"}],"author":"timur","twitter_card":"summary_large_image","twitter_creator":"@TimurKh","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/#article","isPartOf":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/"},"author":{"name":"timur","@id":"https:\/\/blog.wiseowls.co.nz\/#\/schema\/person\/34d0ed30d573b5bc317ea990bd2e0c59"},"headline":"Entity Framework Core 3.1 \u2013 dynamic WHERE clause","datePublished":"2020-08-13T20:20:00+00:00","dateModified":"2026-03-07T11:44:48+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/"},"wordCount":265,"commentCount":1,"image":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg","keywords":["ef-core","sql"],"articleSection":["Development"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/","url":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/","name":"Entity Framework Core 3.1 \u2013 dynamic WHERE clause - Timur and associates","isPartOf":{"@id":"https:\/\/blog.wiseowls.co.nz\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/#primaryimage"},"image":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg","datePublished":"2020-08-13T20:20:00+00:00","dateModified":"2026-03-07T11:44:48+00:00","author":{"@id":"https:\/\/blog.wiseowls.co.nz\/#\/schema\/person\/34d0ed30d573b5bc317ea990bd2e0c59"},"description":"Building dynamic WHERE clauses in EF Core 3.1 with expression trees. Supports nested properties and multiple comparison operators.","breadcrumb":{"@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/#primaryimage","url":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg","contentUrl":"https:\/\/blog.wiseowls.co.nz\/wp-content\/uploads\/2020\/02\/tobias-fischer-PkbZahEG2Ng-unsplash-scaled-e1582017537106.jpg","width":1980,"height":801},{"@type":"BreadcrumbList","@id":"https:\/\/blog.wiseowls.co.nz\/index.php\/2020\/08\/14\/entity-framework-core-3-1-dynamic-where-clause\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.wiseowls.co.nz\/"},{"@type":"ListItem","position":2,"name":"Entity Framework Core 3.1 \u2013 dynamic WHERE clause"}]},{"@type":"WebSite","@id":"https:\/\/blog.wiseowls.co.nz\/#website","url":"https:\/\/blog.wiseowls.co.nz\/","name":"Timur and associates","description":"Notes of an IT contractor","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.wiseowls.co.nz\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.wiseowls.co.nz\/#\/schema\/person\/34d0ed30d573b5bc317ea990bd2e0c59","name":"timur","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/23d55e17d4f0990ee4d12bc6e5dcfb58a292934efd62a185756876379e780b16?s=96&r=pg","caption":"timur"},"sameAs":["https:\/\/x.com\/TimurKh"]}]}},"_links":{"self":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts\/580","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/comments?post=580"}],"version-history":[{"count":6,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts\/580\/revisions"}],"predecessor-version":[{"id":631,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/posts\/580\/revisions\/631"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/media\/391"}],"wp:attachment":[{"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/media?parent=580"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/categories?post=580"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.wiseowls.co.nz\/index.php\/wp-json\/wp\/v2\/tags?post=580"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}