2010-12-10 4 views
6

В чем преимущество написания пользовательского поставщика LINQ над написанием простого класса, который реализует IEnumerable?Зачем писать пользовательский поставщик LINQ?

Например, это quesiton показывает Linq2Excel:

var book = new ExcelQueryFactory(@"C:\Users.xls"); 
var administrators = from x in book.Worksheet<User>() 
        where x.Role == "Administrator" 
        select x; 

Но какова польза над "наивным" реализации как IEnumerable?

+0

Не уверен, почему прибыль от linq-to-excel от IQueryable, но бывают случаи, когда код намного быстрее. – CodesInChaos

ответ

11

Цель поставщика Linq состоит в том, чтобы в основном «перевести» деревья выражений Linq (которые построены за кулисами запроса) в исходный язык запросов источника данных. В случаях, когда данные уже находятся в памяти, вам не нужен поставщик Linq; Линк 2 Объекты прекрасны. Однако, если вы используете Linq для общения с внешним хранилищем данных, например с СУБД или облаком, это абсолютно необходимо.

Основная предпосылка любой структуры запросов заключается в том, что движок источника данных должен выполнять как можно большую часть работы и возвращать только те данные, которые необходимы клиенту. Это связано с тем, что предполагается, что источник данных лучше всего знает, как управлять хранящимися в нем данными, а также потому, что сетевой транспорт данных относительно дорог по времени и поэтому должен быть сведен к минимуму. Теперь, в действительности, эта вторая часть «возвращает только данные, запрашиваемые клиентом»; сервер не может читать мысли вашей программы и знать, что ей действительно нужно; он может дать только то, о чем просили. Здесь интеллектуальный поставщик Linq полностью сдувает «наивную» реализацию. Используя сторону IQueryable Linq, которая генерирует деревья выражений, поставщик Linq может преобразовать дерево выражений в, скажем, инструкцию SQL, которую СУБД будет использовать для возврата записей, запрашиваемых клиентом в инструкции Linq. Наивная реализация потребует получить ВСЕ записи с использованием некоторого широкого оператора SQL, чтобы предоставить клиенту список объектов в памяти, а затем все действия по фильтрации, группировке, сортировке и т. Д. Выполняются клиентом.

Например, предположим, что вы использовали Linq для получения записи из таблицы в базе данных по ее первичному ключу. Поставщик Linq может перевести dataSource.Query<MyObject>().Where(x=>x.Id == 1234).FirstOrDefault() в «SELECT TOP 1 * from MyObjectTable WHERE Id = 1234». Это возвращает ноль или одну запись.«Наивная» реализация, вероятно, отправит серверу запрос «SELECT * FROM MyObjectTable», а затем используйте IEnumerable сторону Linq (которая работает в классах в памяти) для фильтрации. В заявлении вы ожидаете получить результаты 0-1 из таблицы с 10 миллионами записей, какой из них, по вашему мнению, будет выполнять работу быстрее (или даже работать вообще, без нехватки памяти)?

7

Вам не нужно писать поставщик LINQ, если вы хотите использовать только функции LINQ-to-Objects (например, foreach), что в основном работает против списков в памяти.

do необходимо написать поставщик LINQ, если вы хотите проанализировать дерево выражений запроса, чтобы перевести его на что-то другое, например SQL. Вышеупомянутый ExcelQueryFactory, похоже, работает с OLEDB-соединением, например. Это, возможно, означает, что при запросе данных не требуется загружать весь файл excel в память.

3

В целом производительность. Если у вас есть какой-то индекс, вы можете сделать запрос гораздо быстрее, чем то, что возможно на простом IEnumerable<T>.

Linq-To-Sql - хороший пример для этого. Здесь вы преобразовываете оператор linq в другой для понимания сервером SQL. Таким образом, сервер будет выполнять фильтрацию, упорядочивание, ... с использованием индексов и не нужно отправлять всю таблицу клиенту, а затем делает это с помощью linq-to-objects.

Но есть более простые случаи, когда это может быть полезно также:

Если у вас есть индекс дерева над Собственостью Time то диапазон запросы, как .Where(x=>(x.Time>=now)&&(x.Time<=tomorrow)) могут быть оптимизированы много, и не нужно перебирать каждый элемент в перечислимом.

1

LINQ обеспечит отложенное выполнение максимально возможного, чтобы улучшить производительность.

IEnumurable <> и IQueryable <> полностью обеспечит различные программные реализации. IQueryable даст собственный запрос, построив дерево выражений динамически, что обеспечивает хорошую производительность, а затем IEnumurable.

http://msdn.microsoft.com/en-us/vcsharp/ff963710.aspx

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

Смежные вопросы