Логика сопоставления «один ко многим»

#dapper

#dapper

Вопрос:

В руководстве dapper приведен этот пример, чтобы помочь пользователю с несколькими отображениями (один ко многим), Хотя это работает, мне любопытно, почему они заставляют вас хранить заказы в словаре, но затем, в конце концов, они используют linq.Distinct() и возврат из списка. Похоже, было бы чище просто вернуть ordersDictionary.Values, поскольку логика словаря гарантирует отсутствие дубликатов.

 //Tutorial
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{            
    Dictionary<int,Order> orderDictionary = new Dictionary<int, Order>();
    List<Order> list = connection.Query<Order, OrderDetail, Order>(sql, (order, orderDetail) =>
    {
        if (!orderDictionary.TryGetValue(order.OrderID, out Order orderEntry))
        {
            orderEntry = order;
            orderEntry.OrderDetails = new List<OrderDetail>();
            orderDictionary.Add(orderEntry.OrderID, orderEntry);
        }
        orderEntry.OrderDetails.Add(orderDetail);
        return orderEntry;
    }, splitOn: "OrderID")
    .Distinct()
    .ToList();
    return list;
}

//my suggestion
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{            
    Dictionary<int,Order> orderDictionary = new Dictionary<int, Order>();
    //change 1 no need to store into list here
    connection.Query<Order, OrderDetail, Order>(sql, (order, orderDetail) =>
    {
        if (!orderDictionary.TryGetValue(order.OrderID, out Order orderEntry))
        {
            orderEntry = order;
            orderEntry.OrderDetails = new List<OrderDetail>();
            orderDictionary.Add(orderEntry.OrderID, orderEntry);
        }
        orderEntry.OrderDetails.Add(orderDetail);
        return orderEntry;
    }, splitOn: "OrderID"); //change 2 remove .Distinct().ToList()
    return orderDictionary.Values.ToList(); //change 3 return dictionaryValues
}
 

Ответ №1:

Я автор этого руководства: https://dapper-tutorial.net/query#example-query-multi-mapping-one-to-many

почему они заставляют вас хранить заказы в словаре

Для каждого возвращается строка OrderDetail . Итак, вы хотите убедиться, что добавляете OrderDetail к существующему Order , а не создаете новый для каждого OrderDetail . Словарь используется для проверки производительности, чтобы проверить, был ли Order он уже создан или нет.

было бы чище просто вернуть ordersDictionary.Values

Как ваш запрос будет возвращать значения словаря?

Конечно, если вы используете такой метод, как ваш, вы можете сделать

 var list = orderDictionary.Values;
return list;
 

Но как заставить это Connection.Query возвращать значения словаря? Для каждой строки / OrderDetail возвращается порядок, поэтому порядок будет возвращен несколько раз.

Вне Query вашего словарного решения отлично работает и даже является лучшим решением для повышения производительности, но если вы хотите Query вернуть отдельный список заказов без использования Distinct или какого-либо подобного метода, это невозможно.

РЕДАКТИРОВАТЬ: ответить на комментарий

мое предложение возвращает orderDictionary.Values.ToList(); //изменение 3 возвращает значения словаря

Спасибо за ваши отличные отзывы, это всегда ценится 😉

Было бы странно в учебном пособии использовать то, что возвращает запрос, когда нет связи, но использовать словарь для one to many отношений

 // no relationship
var orders = conn.Query<Order>("", ...).Distinct();

// one to many relationship
conn.Query<Order, OrderDetail>("", ...);
var orders = orderDictionary.Values.ToList();
 

Ваше решение лучше по производительности, как вы его используете, в этом нет сомнений. Но именно так люди обычно используют этот Query метод:

 var orders = conn.Query("", ...).Distinct();

var activeOrders = orders.Where(x => x.IsActive).ToList();
var inactiveOrders = orders.Where(x => !x.IsActive).ToList();
 

Они используют то, что Query возвращает метод.

Но опять же, в том, как вы это делаете, нет ничего плохого, это даже лучше, если вы можете это сделать.

Комментарии:

1. прохладный. Прежде всего, большое спасибо за учебник, он был очень полезен при переходе с EF на Dapper. Я добавил второй пример к своему вопросу, демонстрирующий мои настройки. слова моего вопроса не ясно иллюстрируют мою точку зрения.