Я еще не очень хорошо знаю Linq2Sql, и мне было интересно, есть ли хитрость для этого, вероятно, распространенного сценария MVVM. У меня есть контекст данных Linq2Sql, содержащий модели домена, но я получаю из него данные для моего настроенного объекта ViewModel.
var query = from ord in ctx.Table_Orders
select new OrderViewModel()
{
OrderId = ord.OrderId,
OrderSum = ord.OrderSum,
OrderCurrencyId = ord.OrderCurrencyId,
OrderCurrencyView = ord.Currency.CurrencyText
};
Итак, я хочу, чтобы моя ViewModel включала как CurrencyId из объекта домена, так и CurrencyText из связанной таблицы, чтобы он хорошо отображался в представлении.
Этот код прекрасно работает. Он генерирует один вызов БД с объединением для получения CurrencyText. Но модель упрощенная , реальная имеет гораздо больше полей. Я хочу сделать код для повторного использования , потому что у меня много разных запросов, которые возвращают одну и ту же ViewModel. Теперь каждое незначительное изменение в OrderViewModel требует большой поддержки.
Поэтому я переместил код в сам OrderViewModel в качестве конструктора.
public OrderViewModel(Table_Order ord)
{
OrderId = ord.OrderId,
OrderSum = ord.OrderSum,
OrderCurrencyId = ord.OrderCurrencyId,
OrderCurrencyView = ord.Currency.CurrencyText
}
И назовите это так.
var query = from ord in ctx.Table_Orders
select new OrderViewModel(ord);
Проблема : Соединение пропало Запрос БД больше не оптимизирован. Теперь я получаю 1 + N вызовов в базу данных для получения CurrencyText для каждой строки.
Любые комментарии приветствуются. Может быть, я пропустил другой отличный подход.
Вот как далеко я мог бы пройти самостоятельно, чтобы получить код возможность повторного использования . Я создал функцию, которая выполняет работу и имеет несколько параметров. Затем мне нужно явно передать все, что пересекает линию сущности.
var query = ctx.Table_Orders.Select(m =>
newOrderViewModel(m, m.Currency.CurrencyText));
Вызов DB снова оптимизирован. Но это все еще не чувствует, что я там еще! Какие уловки Вы знаете для этого случая?
РЕДАКТИРОВАТЬ: окончательное решение
Благодаря подсказке @Muhammad Adeel Zahid я пришел к этому решению.
Я создал расширение для IQueryable
public static class Mappers
{
public static IEnumerable<OrderViewModel> OrderViewModels(this IQueryable<Table_Order> q)
{
return from ord in q
select new OrderViewModel()
{
OrderId = ord.OrderId,
OrderSum = ord.OrderSum,
OrderCurrencyId = ord.OrderCurrencyId,
OrderCurrencyView = ord.Currency.CurrencyText
};
}
}
Теперь я могу сделать это, чтобы получить весь список
var orders = ctx.Table_Order.OrderViewModels().ToList();
или это, чтобы получить один элемент, или что-то среднее между Где (x => ..)
var order = ctx.Table_Order
.Where(x => x.OrderId == id).OrderViewModels().SingleOrDefault();
И это полностью решает этот вопрос. Сгенерированный SQL идеален, а код для перевода объектов можно использовать повторно. Такой подход должен работать как с LINQ to SQL, так и с LINQ to Entities. (Не проверено с последним) Еще раз спасибо @Muhammad Adeel Zahid