Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dapper multi mapping many to many relationship

Tags:

c#

sql

dapper

I am trying to map an N-N relationship with dapper using as DB MySQL. This is more or less the code.

        var query = new StringBuilder();
        query.Append("SELECT O.Id, O.Email, O.Status, P.Name FROM Owners AS O");
        query.Append(" INNER JOIN OwnerPets OP ON OP.OwnerId = O.Id");
        query.Append(" INNER JOIN Pets AS P ON P.Id = OP.PetId");
        query.Append(" WHERE O.Status = @Status;");

        using (var dbConnection = CreateConnection())
        {
            return dbConnection.Query<Owner, IEnumerable<Pet>, Owner>(query.ToString(), (owner, pets) =>
            {
                owner.Pets = pets.ToList();
                return Owner;
            }, new { Status = status }, splitOn: "OwnerId, PetId");
        }

The query works fine in a SQL client but when I run the code above I get this exception: "When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id. Parameter name: splitOn"

Is it even possible to map a N-N relationship having an intermediate table (OwnerPets)?...If so...what am I doing wrong?

like image 411
osotorrio Avatar asked Jun 23 '16 12:06

osotorrio


People also ask

What is multi mapping in Dapper?

In Dapper, multi mapping is a useful feature that you can use when you have a one-to-one or one-to-many relationship between objects, and you want to load all objects with a single query eagerly. Let's consider our example where we have a one-to-many relationship between an Author and its Book.

Is it better to use join or mapping in Dapper?

For most scenarios, executing a JOIN query is likely to be the right choice. Each record returned from a JOIN query will include data from multiple objects. Dapper provides a feature called Multi mapping to enable you to explicitly map data in a single row to multiple objects.

How to read multiple times from a query in Dapper?

Dapper has an extension **QueryMultiple **which allows reading multiple times from the query. Every **Read **usages gather data from the next SELECT statement in SQL query.

How does multiple mapping work with multiple relationships?

Multiple mapping also works with many to many relationships. The following diagram shows a many-to-many relationship between the Post entity and a Tag entity in a model relating to a Blog application: This is how the associations are represented in code:


1 Answers

I'm not sure if you can get Dapper to return the data directly as you want but you could load the data such that there is a one-to-one relationship between Owners and Pets and then follow it with LINQ query to group the Pets for each Owner.

return dbConnection
    .Query<Owner, Pet, Owner>(
        query,
        (owner, pet) =>
        {
            owner.Pets = owner.Pets ?? new List<Pet>();
            owner.Pets.Add(pet);
            return owner;
        },
        new { Status = status },
        splitOn: "Name"
    )
    .GroupBy(o => o.Id)
    .Select(group =>
    {
        var combinedOwner = group.First();
        combinedOwner.Pets = group.Select(owner => owner.Pets.Single()).ToList();
        return combinedOwner;
    });
like image 127
Dan Roberts Avatar answered Oct 09 '22 14:10

Dan Roberts