Skip to content

In a Nutshell

Adam O'Neil edited this page Jan 23, 2024 · 18 revisions

Dapper.QX revolves around the Query<TResult> class. Use this to encapsulate a SQL statement along with its available parameters. Here's a very simple case.

public class EmployeesResult
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime HireDate { get; set; }
}

public class EmployeesQuery : Query<EmployeesResult>
{
    public Employees() : base("SELECT * FROM [dbo].[Employee] {where} ORDER BY [LastName], [FirstName]")

    [Where("[HireDate]>=@minHireDate")]
    public DateTime? MinHireDate { get; set; }

    [Where("[HireDate]<=@maxHireDate")]
    public DateTime? MaxHireDate { get; set; }
}

Here we've defined a result class followed by a Query class that uses the result. The Query class has two optional parameters MinHireDate and MaxHireDate. Use the query like this:

using (var cn = GetConnection())
{
    var results = await new EmployeesQuery() 
    {
        MinHireDate = new DateTime(2019, 1, 1) 
    }.ExecuteAsync(cn);
}

This same query can be executed like this also. Note how the GetConnection method is passed as an argument without parentheses. This causes the connection to be opened and closed within the scope of the query execution:

var results = await new EmployeesQuery() 
{
    MinHireDate = new DateTime(2019, 1, 1) 
}.ExecuteAsync(GetConnection);

Key points:

  • Use a Query<TResult> class to define your queries, passing the SQL to the base constructor. To make it easy to write an integration test for query, use TestableQuery<TResult> and override its GetTestCasesInner method. See Testing tips for more info.
  • Use {where} or {andWhere} within your SQL to indicate where criteria is injected. Typically you would use one or the other, but in cases like UNION queries where you may need the same criteria injected in multiple queries, you can use both. You can also inject multiple {(and)where} clauses using scoped Where parameters.
  • Add properties to your query class that correspond to parameters in the query. Implement optional criteria as nullable properties decorated with the [Where] or [Case] attributes. There's more you can do with properties, but these are good starting point. The Reference topic lists all the attributes you can use with links to examples.
  • Writing result classes (EmployeesResult in the example above) by hand can be very tedious. I offer a free tool to help with this: Postulate.Zinger
Clone this wiki locally