Search code examples
c#sql-serverdictionarydapper

How to turn dapper result into a dictionary using result mapping


I want to use the splitOn feature denoted here: https://dapper-tutorial.net/result-multi-mapping

to group every Order of the results to a integer property "EmployeeId". I Followed the advice from How to map to a Dictionary object from database results using Dapper Dot Net?

but I am getting a An item with the same key has already been added. so how can I group my orders by EmployeeId?

I cannot modify the Order class and I prefer using a dictionary over creating a class that wraps Order. However, if there is no other way I am open to the idea of wrapping Order

https://dotnetfiddle.net/hn6Sjf

public class Program
{
    public class Order
    {
        public int OrderID { get; set; }
        public int CustomerID { get; set; }
        public DateTime OrderDate  { get; set; }
        public int ShipperID  { get; set; }
    }

    public static void Main()
    {
        string sql = @"
            SELECT TOP 10
                EmployeeID,
                OrderID,
                CustomerID,
                OrderDate,
                ShipperID
            FROM Orders 
            ORDER BY OrderID;
        ";

        using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
        {           
            var rawList = connection.Query<Order>(sql);
            FiddleHelper.WriteTable(rawList);   


                var dict = connection.Query<int, List<Order>, KeyValuePair<int, List<Order>>>(sql,
                    (s, i) => new KeyValuePair<int, List<Order>>(s, i), null, null, true, "OrderID")
                    .ToDictionary(kv => kv.Key, kv => kv.Value);

            FiddleHelper.WriteTable(dict);              
        }
    }
}

Solution

  • Would this meet your needs?

    var dict = connection.Query<int, Order, ValueTuple<int, Order>>(sql,
            (s, i) => ValueTuple.Create(s, i), null, null, true, "OrderID")
            .GroupBy(t => t.Item1, t => t.Item2, (k, v) => new {Key = k, List = v})
            .ToDictionary(kv => kv.Key, kv => kv.List);
    

    Fiddle