Querying into a complex object with Dapper

Blake Rivell picture Blake Rivell · Jul 8, 2017 · Viewed 9.5k times · Source

I have a Customer class with the following properties:

public int Id { get; set; }
public string Name { get; set; }
public int AddressId { get; set; }
public Address Address { get; set; }

My goal is to write a Dapper query that will use an Inner Join to populate the entire Address property within each Customer that is returned.

Here is what I have and it is working but I am wondering if this is the cleanest/simplest way to do it:

StringBuilder sql = new StringBuilder();
using (var conn = GetOpenConnection())
{
    sql.AppendLine("SELECT c.Id, c.Name, c.AddressId, a.Address1, a.Address2, a.City, a.State, a.ZipCode ");
    sql.AppendLine("FROM Customer c ");
    sql.AppendLine("INNER JOIN Address a ON c.AddressId = a.Id ");

    return conn.Query<Customer, Address, Customer>(
        sql.ToString(),
        (customer, address) => {
            customer.Address= address;
            return userRole;
        },
        splitOn: "AddressId"
    ).ToList();
}

I have some concern about adding another property such as:

public Contact Contact { get; set; }

I am not sure how I would switch the syntax above to populate both Address and Contact.

Answer

Aderbal Farias picture Aderbal Farias · Jul 8, 2017

I have coded using Dapper version 1.40 and I have written queries like the way below, I haven't got any issues to populate mote more than one object, but I have faced a limit of 8 different classes those I can map in a query.

public class Customer {
    public int Id { get; set; }
    public string Name { get; set; }
    public int AddressId { get; set; }  
    public int ContactId { get; set; }
    public Address Address { get; set; }
    public Contact Contact { get; set; }
}

public class Address {
    public int Id { get; set; }
    public string Address1 {get;set;}
    public string Address2 {get;set;}
    public string City {get;set;}
    public string State {get;set;}
    public int ZipCode {get;set;}
    public IEnumerable<Customer> Customer {get;set;}
}

public class Contact {
    public int Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<Customer> Customer {get;set;}
}

using (var conn = GetOpenConnection())
{
    var query = _contextDapper
        .Query<Customer, Address, Contact, Customer>($@"
            SELECT c.Id, c.Name, 
                c.AddressId, a.Id, a.Address1, a.Address2, a.City, a.State, a.ZipCode,
                c.ContactId, ct.Id, ct.Name
            FROM Customer c
            INNER JOIN Address a ON a.Id = c.AddressId
            INNER JOIN Contact ct ON ct.Id = c.ContactId", 
            (c, a, ct) =>
            {
                c.LogType = a;
                c.Contact = ct;
                return c; 
            }, splitOn: "AddressId, ContactId")
        .AsQueryable();

    return query.ToList();          
}