Library / SDK
zzzprojects/System.Linq.Dynamic.Core avatar
zzzprojects/System.Linq.Dynamic.Core

System.Linq.Dynamic.Core for String-Based IQueryable Queries

The .NET Standard / .NET Core version from the System Linq Dynamic functionality.

1,712 stars245 forksC#Apache-2.0

At a glance

What is it?
System.Linq.Dynamic.Core is a C# library that turns strings into Dynamic LINQ expressions over IQueryable sources. It fits applications that need configurable filtering and projection, with security controls that require deliberate configuration when queries may come from untrusted users.
Who is it for?
Adopt System.Linq.Dynamic.Core when a .NET application genuinely needs runtime-defined IQueryable filters, sorting, or projections, especially when provider translation is important. Do not choose it as a convenience layer for filters known at compile time.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 52 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why Runtime-Defined LINQ Matters

System.Linq.Dynamic.Core addresses a specific gap between ordinary LINQ and application features whose query rules are not known when the C# code is compiled. Conventional LINQ expresses filters, ordering, and projections as typed expression trees. That is an advantage for code safety and compiler checks, but it is a poor fit when a user must choose fields, operators, or projected values through a configuration interface or text input.

The library targets an IQueryable and accepts those choices as strings. The README example filters customers by city and an Orders.Count threshold, orders them by CompanyName, and returns a new projection containing Name and Phone. The query therefore remains an IQueryable for the duration of the expression-building process. This matters for query providers that translate expressions rather than enumerate ordinary in-memory collections.

The intended users are .NET developers building configurable search, reporting, filtering, or export behavior. It is also relevant to code that already depends on Dynamic LINQ semantics and needs the .NET Core or .NET Standard implementation named by this project. It is not the best choice when every filter is fixed in source code, because typed LINQ already represents that case directly.

How String Expressions Become Queryable Operations

The extension model attaches string-based operations to an existing query source. In the README example, Where receives a predicate string plus positional arguments, OrderBy receives a property name, and Select receives a projection expression. Parameters such as @0 and @1 connect values to the predicate without embedding every value directly in the expression text.

The library parses these strings into LINQ expression information that can be applied to IQueryable. The repository description and README identify this as the.NET Core and.NET Standard port of Dynamic LINQ functionality from the original Microsoft assembly for.NET 4.0. Based on the repository layout, the implementation resides under src/, with tests, examples, a console project, a Blazor project, and documentation alongside it.

Interpolated strings are also supported on the versions listed by the README, including.NET 4.6 and above,.NET Core 2.1 and above,.NET Standard 1.3 and above, and UAP 10.0 and above. This form references variables from C# scope. It does not mean that arbitrary user input can safely be inserted into a parser expression. The documented custom-type and parser restrictions remain relevant to any use of string-based expressions.

Installing the Package and Running the README Query

The README does not provide an installation command or an exact NuGet version. It directs users to the System.Linq.Dynamic.Core package on NuGet, so the documented installation path is to obtain that package from the linked NuGet listing and follow the package instructions for the target.NET project. No package-management command is reproduced here because none appears in the README.

After the package and the relevant namespace imports are configured in an application, the README supplies this first Dynamic LINQ example. It expects a queryable Customers source whose related data includes Orders and whose selected fields include CompanyName and Phone.

csharp
var query = db.Customers
    .Where("City == @0 and Orders.Count >= @1", "London", 10)
    .OrderBy("CompanyName")
    .Select("new(CompanyName as Name, Phone)");

The expression selects customers in London with at least ten orders, orders the result by company name, and projects it to the requested shape. The README does not state what database, entity configuration, or namespaces this example requires, so those details must be established in the consuming project rather than inferred.

Interpolated Dynamic LINQ Without Positional Parameters

For supported targets, the README shows an interpolated-string alternative. Here, cityName and c are local C# variables referenced from the expression. The query shape remains IQueryable-based because it is applied to db.Customers.

csharp
string cityName = "London";
int c = 10;
db.Customers.WhereInterpolated($"City == {cityName} and Orders.Count >= {c}");

This syntax is convenient when filter fields are assembled in application code and the interpolation scope already contains the values. It is different from taking a complete expression from a browser field. The README does not describe a safe parser API for merging unrestricted user-entered fragments, so this example should not be read as permission to concatenate raw request data.

The project also documents ParsingConfig as the mechanism passed to dynamic calls. That matters because security policy is not confined to the expression text. Custom classes, object methods, ordering restrictions, and type providers are controlled through configuration passed to the relevant operations.

Security Boundaries Added in Versions 1.3.0 Through 1.6.0

The strongest evidence about operational risk comes from the README's breaking-change notices. Since v1.3.0, method calls on custom classes are denied by default. An application must mark an eligible class with DynamicLinqType, implement a CustomTypeProvider, or add approved types in DefaultDynamicLinqCustomTypeProvider.cs. The documented goal is to limit calls to predefined classes such as bool, int, and string unless the application explicitly expands the type surface.

Version 1.6.0 tightened three additional boundaries. Calls on object are prohibited, and ToString and Equals are not allowed by default. Enabling those methods requires AllowEqualsAndToStringMethodsOnObject to be set in ParsingConfig. The README connects this change to mitigating risks associated with CVE-2024-51417. That statement documents the project's rationale; it does not amount to an independent assessment of every possible parser exposure.

Ordering is restricted too. RestrictOrderByToPropertyOrField defaults to true, so OrderBy and ThenBy accept properties and fields rather than general expressions. Setting it to false expands what can be used but removes this default boundary. DefaultDynamicLinqCustomTypeProvider also changed to return only types carrying DynamicLinqType. Applications need to review these settings whenever users can influence a dynamic expression.

Target Compatibility and Provider Translation Constraints

The declared framework range is broad. The README lists net35 through net46 and later compatible targets, netstandard1.3, netstandard2.0, netstandard2.1, netcoreapp3.1, net5.0 through net9.0, and uap10.0. Interpolated-string support has its own documented floor and should not be conflated with the full package target range.

An IQueryable source does not remove translation differences. System.Linq.Dynamic.Core builds dynamic LINQ operations, but the downstream provider must support the resulting expression. The README does not enumerate which operators, projection forms, or navigation expressions a specific Entity Framework provider will translate. Its topic list and companion Entity Framework packages indicate relevance to that ecosystem, but they are not a provider compatibility guarantee.

This is the main adoption boundary to test early. Expressions accepted by the dynamic parser can still be unsuitable for a particular database provider. The README confirms string-based querying on IQueryable, while remaining silent about exception behavior, SQL generation, null handling, parameterization details, and client evaluation for individual providers. Those points require validation against the actual query stack rather than inference from the package's framework list.

Maintenance, Licensing, and the Cost of Configuration

The repository is not archived. Its last push was on 2026-09-01, and the listed releases include v1.7.4 on 2026-08-30, v1.7.3 on 2026-07-11, and v1.7.2 on 2026-04-04. Those dates show recent repository and package activity, but the README does not publish a support policy for older target frameworks. Projects tied to an old runtime should therefore check package compatibility before changing versions.

The breaking changes carry a real migration cost. Applications that relied on arbitrary custom methods may need attributes or a custom type provider. Code expecting object methods may need an explicit ParsingConfig decision. Order expressions outside direct property or field access may also change behavior. These are not merely API renames because they alter what the parser accepts.

The repository is licensed under Apache-2.0. The README identifies the license but does not prescribe legal interpretation. Teams still need to review the repository's LICENSE file for their own compliance process. The separate commercial products listed as sponsors are not stated to be required components, so they should not be confused with runtime dependencies of the Apache-2.0 library.

When Typed LINQ Is the Better Alternative

The clearest alternative is ordinary typed LINQ with a compiled expression tree. Its approach differs at the point where the application decides what to query. Typed LINQ encodes field names, predicates, ordering, and projection in C# rather than parsing them from strings at runtime. That reduces the parser and type-provider policy surface, preserves compiler checking, and makes unsupported operations more apparent during development.

Dynamic LINQ becomes preferable when the query shape must come from configuration selected at runtime, or when a reusable filtering component needs to combine user-selected criteria without generating and compiling C# source. System.Linq.Dynamic.Core supplies extension-style operations for that case. Conventional LINQ is the better choice for stable application logic because it removes an unnecessary translation layer.

The README also lists EntityFramework.DynamicLinq, Microsoft.EntityFrameworkCore.DynamicLinq, and other related packages. The README does not document their APIs or compare their internals, so they are not suitable as a mechanism-level comparison here. On the documented evidence, the meaningful choice is between fixed typed expressions and runtime-parsed Dynamic LINQ expressions.

Editorial conclusion

Adopt System.Linq.Dynamic.Core when a .NET application genuinely needs runtime-defined IQueryable filters, sorting, or projections, especially when provider translation is important. Do not choose it as a convenience layer for filters known at compile time. Before adoption, verify that your LINQ provider accepts every expression form you intend to expose, then review the default type and method restrictions with the developers who own parsing configuration. The first release should also pin the package version and include tests for every accepted query syntax.

Frequently asked questions

What does System.Linq.Dynamic.Core do?

It provides string-based Dynamic LINQ operations for an IQueryable, including Where, OrderBy, and Select. This allows filters and projections to be defined at runtime rather than entirely in compiled C# expressions.

How do I install System.Linq.Dynamic.Core?

The README directs users to the System.Linq.Dynamic.Core listing on NuGet. It does not include an exact dotnet add package command or specify a version to select.

Can System.Linq.Dynamic.Core call methods on custom classes?

Not by default. The documented options are applying DynamicLinqType to the class, implementing a CustomTypeProvider for ParsingConfig, or adding approved types in DefaultDynamicLinqCustomTypeProvider.cs.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. zzzprojects/System.Linq.Dynamic.Core on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zzzprojects-system-linq-dynamic-core.svg)](https://hysenlabs.com/projects/zzzprojects-system-linq-dynamic-core)

Was this useful?