Getting started
editInstall the package
Add the Meziantou.Framework.SimpleQueryLanguage package to a project:
dotnet package add Meziantou.Framework.SimpleQueryLanguageThe examples of this documentation omit the using directives: they need using Meziantou.Framework.SimpleQueryLanguage;.
Filter a list
The examples search issues of this type:
internal sealed record Issue(string Title, string Author, bool IsOpen, int Comments, DateTime CreatedAt);Create a QueryBuilder<Issue>, register what each key means, and build the query the user typed:
var queryBuilder = new QueryBuilder<Issue>();
queryBuilder.AddHandler("author", (issue, value) => issue.Author.Equals(value, StringComparison.OrdinalIgnoreCase));
queryBuilder.AddHandler("is", "open", issue => issue.IsOpen);
queryBuilder.AddHandler("is", "closed", issue => !issue.IsOpen);
queryBuilder.AddRangeHandler<int>("comments", (issue, range) => range.IsInRange(issue.Comments));
queryBuilder.SetTextFilterHandler((issue, text) => issue.Title.Contains(text, StringComparison.OrdinalIgnoreCase));
var issues = new[]
{
new Issue("Crash on startup", "alice", IsOpen: true, Comments: 5, new DateTime(2026, 1, 10)),
new Issue("Crash when saving", "bob", IsOpen: true, Comments: 0, new DateTime(2026, 2, 3)),
new Issue("Typo in the readme", "alice", IsOpen: false, Comments: 1, new DateTime(2026, 3, 15)),
};
var query = queryBuilder.Build("is:open author:alice crash");
Assert.Equal(["Crash on startup"], issues.Where(query.Evaluate).Select(issue => issue.Title));author:alicecalls theauthorhandler withalice.is:openmatches the handler registered for the valueopenof the keyis.commentsis a range handler, so it also acceptscomments>=2orcomments:1..5.crashhas no key: it is free text, passed to the text filter.- Terms separated by spaces must all match.
Build parses the query once. Keep the Query<Issue> and call Evaluate for each object.
Filter a database query
To filter an Entity Framework Core DbSet, use ExpressionQueryBuilder<T>: its handlers are expressions that the database can run. See Database queries.
Next steps
- Query syntax: everything users can type.
- In-memory queries: the kinds of handlers, free text and unknown keys.
- Values and dates: how values are parsed, and the date keywords.