Skip to content

Instantly share code, notes, and snippets.

@SamSaffron
Created September 18, 2011 23:43
Show Gist options
  • Save SamSaffron/1225723 to your computer and use it in GitHub Desktop.
Save SamSaffron/1225723 to your computer and use it in GitHub Desktop.
multi map
cnn.QueryMultiple<Table<Order>,Table<OrderLine>,Order>(
@"select * from Orders
select * from OrderLine", (orders, lines) =>
{
var map = lines.ToDictionary(line => line.OrderId);
foreach(var order in orders)
{
order.Lines = map[o.Id];
yield return order;
}
});
// another option, infer Table for single:
cnn.QueryMultiple<Table<Order,User>,OrderLine,Order>(
@"select * from Orders
left join Users u on u.Id = OwnerId
select * from OrderLine", (orders, lines) =>
{
var map = lines.ToDictionary(line => line.OrderId);
foreach(var order in orders.Map((o,u) => {o.Owner = u; return o;}))
{
order.Lines = map[o.Id];
yield return order;
}
});
// Same code today
grid = cnn.QueryMultiple(
@"select * from Orders
left join Users u on u.Id = OwnerId
select * from OrderLine");
var orders = grid.Read<Order,User,Order>((o,u) => {o.Owner = u; return o;}).ToList();
var map = grid.Read<OrderLine>().ToDictionary(line => line.OrderId);
foreach(var order in orders)
{
order.Lines = map[order.Id];
}
@jcolebrand
Copy link

What is this "Table" magic you refer to? I feel lost now.

@SamSaffron
Copy link
Author

It does not exist, but I assume I would make it an IEnumerable where T is something.

@jcolebrand
Copy link

I went back and pulled up my existing code and compared it to this and my brain locked onto what you were asking and my jaw dropped. I'm not entirely sure I would appreciate this addition to the code, as I use it fairly differently. Here's one of my random methods, slightly anonymized:

    public static RecordDTO SprocName(string param1, string param2) {
        List<ThingIds> Things; /* the field returned is called ItemID */
        List<UnitSet> UnitSet;
        List<TemperatureData> Temps;
        List<UnitIntervals> UnitIntervals;

        using ( var con = DataAccessMaster.GetOpenConnection() ) {
            using ( var multi = con.QueryMultiple( "SprocName", new { Param1 = param1, Param2 = param2} ) ) {
                Things = multi.Read<ThingIds>().ToList();
                UnitSet = multi.Read<UnitSet>( ).ToList( );
                Temps = multi.Read<TemperatureData>( ).ToList( );
                UnitIntervals = multi.Read<UnitIntervals>( ).ToList( );
            }
        }
        return new RecordDTO {
            Things = Things,
            UnitSet = UnitSet,
            Temps = Temps,
            UnitIntervals = UnitIntervals
        };
    }

@WilliamBZA
Copy link

Isn't there a bug in the second option? Shouldn't it return o instead of u?

// another option, infer Table for single:

cnn.QueryMultiple<Table<Order,User>,OrderLine,Order>(
@"select * from Orders
left join Users u on u.Id = OwnerId
select * from OrderLine", (orders, lines) =>
{
   var map = lines.ToDictionary(line => line.OrderId);
   foreach(var order in orders.Map((o,u) => {o.Owner = u; return o;}))
   {
      order.Lines = map[o.Id];
      yield return order;
   }
});

@jcolebrand
Copy link

If so that applies to the third example line as well

@SamSaffron
Copy link
Author

@william true ... changed it

@JasonPunyon
Copy link

@SamSaffron: .ToDictionary probably isn't right in any of the examples (why would we need multimap at all? :))

Can we get rid of even more boilerplate? For the multimap, I'd think all you really need to specify are the key selectors and the way to combine the results...

var results = cnn.Query<User, Order, OrderLine>
            ("select * from Users;select * from Order;select * from OrderLine")
            .Map((user, order) => { order.User = user; return order; })
            .MultiMap(order => order.Id, 
                      line => line.OrderId,
                      (order, orderLines) => order.OrderLines = orderLines.ToList());

@jcolebrand
Copy link

@JasonPunyon isn't he trying to avoid chaining in his revision?

@JasonPunyon
Copy link

@jcolebrand: He hasn't told me so I wouldn't know. I just followed a tweet here :)

@jcolebrand
Copy link

@JasonPunyon me too! ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment