Using the RowDelegate approach avoids having to iterate through the returned IList<T> a second time to do the grouping:
public class QueryWithRowDelegateDictionaryCreator<TKey, T> { private readonly Func<T, TKey> keySelector; private readonly IDictionary<TKey, IList<T>> dictionary = new Dictionary<TKey, IList<T>>(); public QueryWithRowDelegateDictionaryCreator(Func<T, TKey> keySelector) { this.keySelector = keySelector; } public void RowDelegate<TUnused>(object obj, object parameterObject, IList<TUnused> unused) { T item = (T)obj; TKey key = keySelector(item); IList<T> list; if (dictionary.TryGetValue(key, out list) == false) { list = new List<T>(); dictionary[key] = list; } list.Add(item); } public IDictionary<TKey, IList<T>> Dictionary { get { return dictionary; } } } public CategorySqlMapDao : ICategoryDao { private ISqlMapper sqlMapper; public CategorySqlMapDao(ISqlMapper sqlMapper) { this.sqlMapper = sqlMapper; } public IList<Product> FindProducts(int categoryId) { return sqlMapper.QueryForList("FindProductsCategoryId", categoryId); } public IDictionary<int, IList<Product> FindProducts(int[] categoryIds) { var dictionaryCreator = new QueryWithRowDelegateDictionaryCreator<int, Product>(p => p.CategoryId); sqlMapper.QueryWithRowDelegate("FindProductsCategoryIds", categoryIds, dictionaryCreator.RowDelegate); return dictionaryCreator.Dictionary; } }