#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. Я добавил второй пример к своему вопросу, демонстрирующий мои настройки. слова моего вопроса не ясно иллюстрируют мою точку зрения.