Я изо всех сил пытаюсь понять, как мне следует применять dapper в моем приложении.У меня есть n-уровневое приложение mvc, и у меня есть некоторый опыт работы с EF.Даже если я считаю, что EF - это хорошо, я не прошел обучение, чтобы упростить его и не бороться с производительностью.В новом проекте мы решили попробовать dapper, в основном, чтобы получить контроль над sql и, надеюсь, получить хорошую производительность.
Фон
Я создал многоуровневую аппликацию (ядро) с этими слоями Web - mvc
Сервис - Бизнес-уровень для обработки бизнес-логики Данные - доступ к данным для доступа к даннымсервер ms sql
Я пошел дальше и начал внедрять UnitOfWork и универсальные репозитории в уровне данных.
Обычная структура в базе данных будет иметь вид
Order
ref to User
ref to Address
OrderLine
ref to Product
И вВо многих случаях я хочу получить несколько заказов со всеми линиями и продуктами.
Итак, я сделал так, чтобы свойства навигации для моделей сущностей были такими же, как в EF, и заполняли их с помощью dapper, используя мультизапрос, или разбивали результат на разные сущности и отображали их на графике.
Проблема
Проблема, с которой я сталкиваюсь - это когда я делаю вставку.У меня есть sqlextension, которое сопоставляет свойства столбцам таблицы.Но навигация также будет отображаться по умолчанию.Я понимаю, что могу украсить атрибутами и читать их при отображении, но по мере того, как я Google, я осознаю, что, возможно, мне следует удалить шаблон UnitOfWork, а также репозиторий, делая слой данных «сверхтонким» и просто выставляя соединение,Тогда сервисный слой будет вызывать Dapper с правильным sql, что я и сделал бы сегодня, но с репозиториями.
Я бы также отбросил свойства навигации и выбрал каждый объект самостоятельно, и объединил их вViewModel.
Моя проблема с этим заключается в том, что если мы возьмем таблицу заказов выше, мне нужно будет сделать что-то вроде этого, чтобы получить полный список (обычно с постраничной страницей, также я удалил пользователя / адрес)
var listModel = new OrderListViewModel();
var orders = orderService.GetAll();
foreach(var order in orders) {
var orderModel = new OrderViewModel(); // also map fields
var orderLines = orderService.GetOrderLinesForOrder(order.OrderId);
foreach(var orderline in orderLines) {
var orderLineModel = new OrderLineViewModel(); // also map fields
var product = productService.GetProduct(orderline.ProductId);
orderLineModel.Product = new ProductViewModel(); // also map fields
orderModel.OrderLines(orderLineModel);
}
listModel.Orders.Add(orderModel);
}
Это создаст ALOT запросов (почти как EF-ленивая загрузка).Таким образом, я мог бы сделать сопоставление
var orders = orderService.GetAll();
var orderLines = orderService.GetOrderLinesForOrders(orders.Select(o => o.OrderId).ToArray() ); // get all orderlines for all orders
var products = productService.GetProductsForOrderLines(orderLines.Select(p => p.OrderLineId).ToArray() ); // get all products for all orderlines
foreach(var order in orders) {
var orderModel = new OrderViewModel(); // also map fields
var orderLines = orderLines.Where( o => o.OrderId == order.OrderId );
foreach(var orderline in orderLines) {
var orderLineModel = new OrderLineViewModel(); // also map fields
var product = products.First(p => p.ProductId == orderline.ProductId);
orderLineModel.Product = new ProductViewModel(); // also map fields
orderModel.OrderLines(orderLineModel);
}
listModel.Orders.Add(orderModel);
}
Это будет генерировать гораздо меньше запросов SQL и является оптимальным по производительности, я думаю.Я знаю, что может быть проблема с более чем 2100 (?) Параметрами, но я думаю, что это не будет проблемой в моем случае.Проблема в том, что многие из наших таблиц имеют разный статус и имеют много связей с другими таблицами.Мне бы приходилось все время выполнять множество этих запросов.
Когда я впервые делал репозиторий и навигацию, я делал бы это как
repo.Get<Order, OrderLines, Product, Order>(sqlThatWouldJoinAllTables);
// split and map the structure into order Entity and just return that
Таким образом, я мог бы просто вызвать orderService.GetAll () и получить график заказа, линий заказов и продуктов.
Я не знаю, какое из решений является «наилучшей практикой».Я пытался найти хороший проект с открытым исходным кодом, используя слои и щегольство, чтобы получить реальное использование в мире, но безуспешно.Подход к удалению навигационных свойств также устраняет некоторые цели сервисного уровня, поскольку я в некотором роде перенес часть бизнес-логики на контроллер mvc.
Я не могу найти хорошую практику, как мне двигаться вперед, пожалуйста, совет.