Expression Trees
Four different ways to express a filter, from a plain anonymous object to fully composable query trees.
The four forms
A filter can be an anonymous object, a LINQ expression, an ExpandoObject/dictionary, or a QueryField/QueryGroup tree — each trades some expressiveness for simplicity, or vice versa. The first three only support equality; the last supports every comparison operator.
Anonymous object
var customer = connection.Query<Customer>(new { Id = 10045 }).FirstOrDefault();
Or with multiple columns:
var customer = connection.Query<Customer>(new { FirstName = "John", LastName = "Doe" }).FirstOrDefault();
This is the simplest and most direct form, but the compiler doesn’t validate it against the entity model — a renamed column won’t trigger a compile error — and it only supports equality comparisons.
LINQ expressions
var customers = connection.Query<Customer>(e =>
states.Contains(e.State) && e.IsActive == false);
This is the most common form for entity-model operations, though its parser is intentionally narrower than a full LINQ-to-SQL provider — complex expressions are where QueryGroup takes over.
ExpandoObject and Dictionary
var where = new Dictionary<string, object>
{
{ nameof(Customer.FirstName), "John" },
{ nameof(Customer.LastName), "Doe" }
};
var customer = connection.Query<Customer>(where).FirstOrDefault();
An ExpandoObject works the same way as an IDictionary<string, object> here — both are handy when the filter columns are only known at runtime. Like the anonymous-object form, they only support equality; reach for QueryField/QueryGroup for anything else.
QueryField and QueryGroup
var where = new[]
{
new QueryField(nameof(Customer.State), Operation.In, states),
new QueryField(nameof(Customer.IsActive), false),
new QueryField(nameof(Customer.DateOfBirth), Operation.GreaterThanOrEqual, DateTime.Parse("1970-01-01"))
};
var customers = connection.Query<Customer>(where);
More verbose than a LINQ expression, but it’s the most powerful and explicit way to compose a filter, and the one to reach for once a LINQ expression gets awkward to write or maintain.