C #, Linq2SQL - трюки для получения объекта ViewModel с данными соотношения? -- c# поле с участием asp.net-mvc поле с участием linq-to-sql поле с участием mvvm пол Связанный проблема

C#, Linq2SQL - tricks to fetch a ViewModel object with relation data?


2
vote

проблема

русский

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

Этот код работает отлично. Он генерирует один вызов БД с присоединением, чтобы получить валютный элемент. Но модель упрощена , реальная есть много полей. Я хочу сделать код многоразовый потому, что у меня есть много разных запросов, что возвращает одинаковую просмотру. Теперь каждое незначительное изменение в 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);   

Проблема : присоединение ушло db Query не оптимизировано. Теперь я получаю 1 + N вызовов в базу данных, чтобы получить валютный элемент для каждой строки.

Любые комментарии приветствуются. Может быть, я скучал по разным отличным подходу.

Вот как далеко я мог бы самостоятельно получить, чтобы получить код Reurative . Я создал функцию, которая выполняет задание и имеет несколько параметров. Тогда мне нужно явно пройти все, что имеет пересекли линейку сущности.

 <код> var query = ctx.Table_Orders.Select(m =>        newOrderViewModel(m, m.Currency.CurrencyText));   

Вызов БД снова оптимизирован. Но это все еще не чувствует, что пока я есть там! Какие трюки вы знаете для этого дела?


Редактировать: окончательное решение Благодаря намеканию @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 = & gt; ..)

 <код> var order = ctx.Table_Order    .Where(x => x.OrderId == id).OrderViewModels().SingleOrDefault();   

И это полностью решает этот вопрос. Сгенерированный SQL идеален, и код для перевода объектов многоразовый. Подобный подход должен работать как с Linq для SQL, так и для Linq к объектам. (Не проверяется с последним) Снова спасибо @muhammad Adeel Zahid

Английский оригинал

I don't know Linq2Sql so well yet and I was wondering if there is a trick for this probably common MVVM scenario. I have Linq2Sql data context containing Domain models, but I am fetching data for my customized ViewModel object from it.

var query = from ord in ctx.Table_Orders         select new OrderViewModel()         {             OrderId = ord.OrderId,             OrderSum = ord.OrderSum,             OrderCurrencyId = ord.OrderCurrencyId,             OrderCurrencyView = ord.Currency.CurrencyText         }; 

So i want my ViewModel to inculde both CurrencyId from domain object and the CurrencyText from related table to show it nicely in the View.

This code works great. It generates one DB call with join to fetch the CurrencyText. But the model is simplified, real one has many more fields. I want to make the code reusable because I have many different queries, that returns the same ViewModel. Now every minor change to OrderViewModel requires lots of maintainance.

So I moved the code to OrderViewModel itself as a constructor.

public OrderViewModel(Table_Order ord) {     OrderId = ord.OrderId,     OrderSum = ord.OrderSum,     OrderCurrencyId = ord.OrderCurrencyId,     OrderCurrencyView = ord.Currency.CurrencyText } 

And call it like this.

var query = from ord in ctx.Table_Orders         select new OrderViewModel(ord); 

The Problem: The join is gone DB query is no more optimised. Now I get 1+N calls to database to fetch CurrencyText for every line.

Any comments are welcome. Maybe I have missed different great approach.

This is how far i could get on my own, to get the code reusability. I created a function that does the job and has multiple parameters. Then I need to explicitly pass it everything that has crossed the line of entity.

var query = ctx.Table_Orders.Select(m =>        newOrderViewModel(m, m.Currency.CurrencyText)); 

The DB call is again optimized. But it still does not feel like I am there yet! What tricks do You know for this case?


EDIT : The final solution Thanks to a hint by @Muhammad Adeel Zahid I arrived at this solution. I created an extension for 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                 };     } } 

Now i can do this to get all list

var orders = ctx.Table_Order.OrderViewModels().ToList(); 

or this to get a single item, or anything in between with Where(x => ..)

var order = ctx.Table_Order    .Where(x => x.OrderId == id).OrderViewModels().SingleOrDefault(); 

And that completely solves this question. The SQL generated is perfect and the code to translate objects is reusable. Approach like this should work with both LINQ to SQL and LINQ to Entities. (Not tested with the latter) Thank You again @Muhammad Adeel Zahid

</div
           

Список ответов

1
 
vote
vote
Лучший ответ
 

Всякий раз, когда мы запрашиваем базу данных, мы в основном требуем либо перечисления объектов (более одного записей в БД), либо мы хотим единого объекта (одна запись в БД). Вы можете написать свой сопоставленный код в методе, который возвращает перечисление для всей таблицы, такой как

 <код> public IEnumerable<OrderViewModel> GetAllOrders() {     return from ord in ctx.Table_Orders         select new OrderViewModel()         {             OrderId = ord.OrderId,             OrderSum = ord.OrderSum,             OrderCurrencyId = ord.OrderCurrencyId,             OrderCurrencyView = ord.Currency.CurrencyText         };  }    

Теперь вы можете захотеть отфильтровать эти записи и вернуть другое перечисление, например, на ValueID

 <код> public IEnumerable<OrderViewModel> GetOrdersByCurrency(int CurrencyID) {       return GetAllOrders().Where(x=>x.CurrencyId == CurrencyID); }   

Теперь вы также можете найти одну запись из всех этих моделей просмотра

 <код> public OrderViewModel GetOrder(int OrderID) {       return GetAllOrders().SingleOrDefault(x=>x.OrderId == OrderID); }   

Красота iEnumerable - это то, что она продолжает добавлять условия для запроса и не выполняют его, пока не требуется. Таким образом, ваша таблица не будет загружена, если вы не хотите этого, и вы сохранили свой код в одном месте. Теперь, если есть какие-либо изменения в сопоставлении ModeMODEL или в самом запросе, он должен быть сделан в методе Getallorders (), остаток кода останется без изменений

 

Whenever we query the database, we mostly require either enumeration of objects (more than one records in db) or we want a single entity (one record in db). you can write your mapping code in method that returns enumeration for whole table like

public IEnumerable<OrderViewModel> GetAllOrders() {     return from ord in ctx.Table_Orders         select new OrderViewModel()         {             OrderId = ord.OrderId,             OrderSum = ord.OrderSum,             OrderCurrencyId = ord.OrderCurrencyId,             OrderCurrencyView = ord.Currency.CurrencyText         };  }  

Now you may want to filter these records and return another enumeration for example on currencyID

public IEnumerable<OrderViewModel> GetOrdersByCurrency(int CurrencyID) {       return GetAllOrders().Where(x=>x.CurrencyId == CurrencyID); } 

Now you may also want to find single record out of all these view models

public OrderViewModel GetOrder(int OrderID) {       return GetAllOrders().SingleOrDefault(x=>x.OrderId == OrderID); } 

The beauty of IEnumerable is that it keeps adding conditions to query and does not execute it until it is needed. so your whole table will not be loaded unless you really want it and you have kept your code in single place. Now if there are any changes in ViewModel Mapping or in query itself, it has to be done in GetAllOrders() method, rest of code will stay unchanged

</div
 
 
   
   
1
 
vote

Вы можете избежать проблем N + 1 запросов, имея Linq2SQL с нетерпением загрузка ссылок, которые вам нужно построить ваши программы просмотра. Таким образом, вы можете создать один список объектов (и некоторые ссылки на объекты) и используете его, чтобы построить все. Посмотрите на это Blog Post .

Одно слово предупреждения, хотя и: этот метод (настройка погрузчиков для контекста данных Linq2SQL) можно сделать только один раз за контекст данных. Если вам нужно выполнить второй запрос с другой конфигурацией для нетерпеливой загрузки, вы должны повторно вывести свой контекст данных. Я автоматизировал это простым классом обертки вокруг моего контекста.

 

You can avoid the N+1 queries problem by having Linq2SQL eagerly load the referenced entites you need to construct your viewmodels. This way you can build one list of objects (and some referenced objects) and use it to construct everything. Have a look at this blog post.

One word of warning though: This technique (setting LoadOptions for the Linq2SQL data context) can only be done once per data context. If you need to perform a second query with a different eager loading configuration, you must re-initalize your data context. I automated this with a simple wrapper class around my context.

</div
 
 
       
       

Связанный проблема

0  Ошибка структуры объекта: ошибка загрузки указанного ресурса метаданных  ( Entity framework error error loading specified metadata resource ) 
Я знаю, что это известная проблема, но решение для моего случая не в других вопросах, я думаю. У меня есть проект в C #. В этом проекте у меня есть мой EDMX...

2  Обработка ошибок в свойствах, я знаю, что это плохо, нужно исправить, хотя  ( Error handling in properties i know its bad need fix though ) 
Я знаю свою плохую практику, чтобы поставить обработку ошибок в свойствах, я просто хочу знать , где я должен положить ошибку обработки ошибок. Я знаю, что з...

0  Как нарисовать в автономном режиме круг 1500 метров в диапазоне Geocoordinate в Windows Phone 8  ( How to draw offline circle of 1500 meters range over the geocoordinate in window ) 
Я хочу нарисовать автономный круг над геокоординаном в Windows Phone Этот круг составляет 1500 метров, и он ищет цель в этом диапазоне это мой образ, где у...

-4  Будет вернуться внутрь памяти утечки для петли?  ( Will a return inside of a for loop leak memory ) 
в основном все, что мне нужно знать, является ли возвращение внутри цикла для цикла в C #. <код> for (int i = 0; i <= 20; i++ ) { if(i == 10) re...

1  Разница между несколькими наследованиями и интерфейсами в C #  ( Difference between multiple inheritance and interfaces in c sharp ) 
делает C # действительно поддерживать многократное наследование. Люди говорят, что он поддерживает многократное наследование в виде интерфейсов? Но я не думаю...

5  Можем ли мы использовать ответ .Flush () вместо ответа. Денды ()  ( Can we use response flush instead of response end ) 
<Код> Response.End() генерирует <код> ThreadAbortException . Использование <код> HttpContext.Current.ApplicationInstance.CompleteRequest вместо этого не р...

2  Обращайтесь с событиями для динамического (время выполнения) - vb.net  ( Handle events for dynamic run time controls vb net ) 
У меня есть элемент управления WebBrowser, который создается и добавляется в форму во время выполнения. Как подключить этот элемент управления подпрограммой...

4  Создайте VCARD, который можно скачать на Android с помощью ASP.NET  ( Generate vcard that can be downloaded on android using asp net ) 
Я пробую довольно некоторое время, чтобы сгенерировать VCARD, используя ASP.NET (C #), которые можно загрузить на устройство Android. Процесс генерации карт...

1  Как довольно печатать метод итератора  ( How to pretty print the iterator method ) 
Я хочу получить имя метода со своими аргументами метода итератора и я борюсь, чтобы найти простое решение. Итераторы генерируются компилятором в результате. И...

0  Как бы я пошел на рисование в программе краски с чувствительностью давления?  ( How would i go about drawing in a paint program with pressure sensitivity ) 
Я пишу программу краски в родах, используя C # .NET / WinForms и чувствительность к давлению является обязательным. У меня все настроено и получаю информацию ...

0  Присоединиться к запросу с LINQ  ( Join query with linq ) 
Я пытаюсь здесь сделать несколько левых присоединиться к запросу LINQ, но я бы сказал, что понятия не имею, как материализовать эту идею. в основном вот 3 с...

0  Streaminsight и долгосрочные запросы  ( Streaminsight and long running queries ) 
У меня есть приложение, построенное на вершине Streaminsight 1.2, который имеет несколько постоянных запросов, выполняющих некоторые расчеты в операторах опре...

3  Как мне расположить эллипс на сетке Silverlight?  ( How do i position an ellipse on a silverlight grid ) 
Я создаю приложение Silverlight, которое позволит вам нажать в два места на экране и нарисовать эллипс, основной ось которого начинается и заканчивается в мес...

1  Как я могу прочитать все предметы питания?  ( How do i read all feed items ) 
Я хочу прочитать все элементы подачи в C #. Решения, которые я обнаружил, только для новейших элементов, таких как только последние 10 дней. У кого-нибудь е...

-2  Гольф HCP Calculator  ( Golf hcp calculator ) 
Я работаю над программой в ASP.NET MVC, где моя цель - сделать показатель для гольфа. в Golf у каждого игрока есть гандикап, который дает им ряд дополнитель...

Связанный проблема

0  Ошибка структуры объекта: ошибка загрузки указанного ресурса метаданных 
2  Обработка ошибок в свойствах, я знаю, что это плохо, нужно исправить, хотя 
0  Как нарисовать в автономном режиме круг 1500 метров в диапазоне Geocoordinate в Windows Phone 8 
-4  Будет вернуться внутрь памяти утечки для петли? 
1  Разница между несколькими наследованиями и интерфейсами в C # 
5  Можем ли мы использовать ответ .Flush () вместо ответа. Денды () 
2  Обращайтесь с событиями для динамического (время выполнения) - vb.net 
4  Создайте VCARD, который можно скачать на Android с помощью ASP.NET 
1  Как довольно печатать метод итератора 
0  Как бы я пошел на рисование в программе краски с чувствительностью давления? 
0  Присоединиться к запросу с LINQ 
0  Streaminsight и долгосрочные запросы 
3  Как мне расположить эллипс на сетке Silverlight? 
1  Как я могу прочитать все предметы питания? 
-2  Гольф HCP Calculator