Простой способ возврата анонимных типов (чтобы сделать возможным MVC с использованием LINQ)

Я хотел бы реализовать MVC при использовании LINQ (в частности, LINQ-to-entities). Я бы сделал это так, чтобы контроллер сгенерировал (или вызвал что-то, что генерирует) набор результатов с использованием LINQ, а затем вернул его в представление для отображения данных. Проблема в том, что если я сделаю:

return (from o in myTable select o);

Все столбцы считываются из базы данных, даже те (возможно, десятки), которые мне не нужны. И, что более важно, я не могу сделать что-то вроде этого:

return (from o in myTable select new { o.column });

потому что нет способа сделать анонимные типы типобезопасными! Я точно знаю, что в 3.5 нет красивого и чистого способа сделать это (это не чисто...), а как насчет 4.0? Есть ли что-то запланированное или даже предложенное? Без чего-то вроде утиного ввода для LINQ или безопасных для типов анонимных возвращаемых значений (мне кажется, что компилятор, безусловно, должен быть на это способен), кажется, почти невозможно четко отделить контроллер от представления.


person BlueRaja - Danny Pflughoeft    schedule 15.03.2010    source источник
comment
Когда вы работаете с формой, вы должны привыкнуть к мысли о том, что sql выбирает все столбцы таблицы. Если вы пишете запросы, которые выбирают только некоторые из них, вы можете использовать sql в первую очередь. Если у вас есть десятки свойств ваших объектов, то это ваша проблема. Ваши объекты должны быть меньше, и вы должны подумать о том, как вы можете это исправить. Анонимные типы не должны передаваться, особенно в качестве моделей представления.   -  person Mattias Jakobsson    schedule 17.03.2010
comment
@Mattias: К сожалению, жизнь не так проста. Например, рассмотрим случай, когда я выбираю несколько столбцов из разных таблиц, включая массив объектов, выбранных с помощью внутреннего запроса LINQ. Насколько мне известно, нет способа вернуть это как один объект EF - он должен быть нового типа, а определение нового конкретного типа для каждого такого запроса смехотворно громоздко.   -  person BlueRaja - Danny Pflughoeft    schedule 17.03.2010
comment
Мне кажется, у вас очень плохая модель. Ваш объект должен иметь необходимые ссылки, и вы можете просто использовать метод Include() в EF (чтобы быстро загрузить эти данные). Если вы перестанете думать о данных как о разных столбцах в разных таблицах и больше о своей модели (больше ООП), скорее всего, с ней будет намного проще работать. Итог: если вы чувствуете необходимость передавать анонимные типы, вы, скорее всего, делаете что-то еще неправильно.   -  person Mattias Jakobsson    schedule 17.03.2010


Ответы (6)


Используйте слой модели представления. Ваше представление должно знать, что оно собирается отображать. Я предполагаю, что можно создать представление, которое просто форматирует многомерный массив данных, но это не лучшая причина для использования решения MVC. Однако вы можете заполнить модель представления анонимным объектом для использования в своем представлении.

person Nick Larsen    schedule 15.03.2010

Анонимные типы в первую очередь предназначены для использования внутри метода. Они не подходят для связи между методами.

Если вам нужно передать набор данных между двумя функциями, лучше всего создать новый тип, обертывающий данные, или использовать группу неудачников, например Tuple<T1,T2> или KeyValuePair<TKey,TValue>.

person JaredPar    schedule 15.03.2010
comment
за исключением сценария, основанного на отражении, и в этом случае для них есть несколько хороших применений (например, в html-помощниках фреймворка MVC) - person Nick Larsen; 16.03.2010
comment
@Jared: За исключением того, что с LINQ это совсем не так - объекты LINQ, безусловно, предназначены для передачи, но вы просто не можете сделать это на C # из-за языковых ограничений. Однако это можно сделать в VB.net. - person BlueRaja - Danny Pflughoeft; 16.03.2010
comment
@BlueRaja, извините, что неверно. Они могут передаваться на любом языке как System.Object. Они не могут быть сильно переданы ни в одном из языков, поскольку анонимные типы хорошо анонимны. Их нельзя определить напрямую в любом месте, которое может отображаться в метаданных. В VB.net (и С# 4.0) вы можете обойти это, обратившись к ним со слабой типизацией, но это не то, о чем просит ОП. - person JaredPar; 16.03.2010

Как насчет этого?

Я предполагаю, что у вас есть класс сущностей для таблицы myTable (назовем его MyTableEntity), так почему бы вам не создать экземпляр нового объекта MyTableEntity и не использовать инициализатор объекта для заполнения только тех столбцов, которые вам нужны?

return (from o in myTable select new MyTableEntity { AColumn = o.column });

Это не будет преобразовано в SELECT *, как вы просили, но у вас все равно будет способ передать строго типизированный объект в представление.

Вы должны быть осторожны, чтобы просто использовать инициализированные свойства внутри представления, и все.

Имеет ли это смысл для вас?

person empz    schedule 26.04.2010
comment
Это хорошая идея - я попробую это на работе, когда у меня будет шанс (по крайней мере, в течение нескольких дней) - person BlueRaja - Danny Pflughoeft; 27.04.2010

Поскольку никто даже не попытался ответить на мой вопрос, отвечу сам.

Оказывается, C# 4.0 поддерживает утиную типизацию — они называют это динамической типизацией. Однако при использовании динамических типов для возврата анонимных типов мы теряем преимущества сильных типов:

  • Проверка типов во время компиляции
  • Представление
  • Интеллисенс

Я открыл запрос функции, чтобы иметь строго типизированные анонимные возвращаемые типы class#" rel="nofollow noreferrer">здесь — если вы считаете, что это полезное дополнение к C# 5, перейдите по ссылке и сообщите об этом команде разработчиков .Net!

person BlueRaja - Danny Pflughoeft    schedule 09.04.2010

В .NET 4.0 анонимные типы можно легко преобразовать в ExpandoObjects, и, таким образом, все проблемы устраняются за счет затрат на само преобразование. Ознакомьтесь с здесь

person Adaptabi    schedule 14.04.2011

Вы можете легко преобразовать анонимные типы в динамические объекты, вот простая реализация Donymous объекты (динамические анонимные объекты), которые могут заполняться из Anonymous объекта или DataReader.

person Faraz M. Khan    schedule 23.03.2014