2010-04-07 2 views
4

Мне было интересно узнать о разнице в производительности между этими двумя сценариями и каковы могут быть недостатки друг от друга?Возврат IQueryable или перечислимого объекта

Первый сценарий:

public class Helper //returns IQueryable 
{ 
    public IQueryable<Customer> CurrentCustomer 
    { 
     get{return new DataContext().Where(t=>t.CustomerId == 1); 
    } 
} 

public class SomeClass 
{ 
    public void Main() 
    { 
     Console.WriteLine(new Helper().CurrentCustomer.First().Name; 
    } 
} 

Второй сценарий:

public class Helper //returns Enumerated result 
{ 
    public Customer CurrentCustomer 
    { 
     get{return new DataContext().First(t=>t.CustomerId == 1); 
    } 
} 

public class SomeClass 
{ 
    public void Main() 
    { 
     Console.WriteLine(new Helper().CurrentCustomer.Name; 
    } 
} 

Спасибо заранее.

ответ

4

Ну, основное отличие, которое я вижу, это когда запрос выполняется и что еще вы можете сделать с запросом.

Например, предположим, что у вашего объекта Customer есть несколько больших полей. Используя второй подход, вы всегда будете получать их. С помощью первого подхода вы могли написать:

string name = helper.CurrentCustomer.Select(x => x.Name).First(); 

что только тогда нужно будет запрашивать одно поле в базе данных. С точки зрения синхронизации запрос будет выполнен только тогда, когда вы действительно запрашиваете данные (так как он может подождать, пока вы не воспользуетесь Select, чтобы выяснить, что поставить в запрос в приведенном выше случае). У этого есть плюсы и минусы - это может усложнить рассуждение, но это тоже может сэкономить. Что касается стороны «рассуждения о», вы знаете, что, как только у вас есть клиент, у вас есть объект, с которым вы можете просто работать. Если вы используете один и то же запрашиваемое дважды, хотя, вы должны знать, собирается ли ваш провайдер LINQ запроса кэшировать результат ... если вы напишете:

IQueryable<Customer> currentCustomerQuery = helper.CurrentCustomer; 
Customer x = currentCustomerQuery.First(); 
Customer y = currentCustomerQuery.First(); 

будет этот вопрос запрос один или два раза? Я подозреваю, что это очень зависит от провайдера, но я не хотел бы делать какие-либо догадки о конкретных.

Другая вещь, о которой нужно подумать, - это то, как легко использовать API, который вы строите. Лично мне обычно легче было бы использовать API, который дает мне данные, которые я хочу, а не запрос, из которого я могу получить эти данные. С другой стороны, это является немного менее гибким.

Один из вариантов заключается в том, чтобы разрешить и - иметь метод GetCurrentCustomerQuery() и GetCurrentCustomer(). (Я, вероятно, не сделал бы их свойств самостоятельно, но это всего лишь вопрос личных предпочтений.) Таким образом, вы можете получить гибкость, которая вам нужна, когда она вам действительно нужна, но иметь простой способ просто получить текущего клиента в качестве объекта ,

+0

Можете ли вы объяснить, почему вы не сделали бы их свойствами? Благодарю. – Tarik

+0

@Tarik: Похоже, что они делают слишком много работы, чтобы быть свойствами - по крайней мере, если она фактически выполняет запрос базы данных. Обычно я не ожидаю, что свойство getter сделает много работы. С другой стороны, я полагаю, что многие LINQ работают со свойствами, которые * делают * делают запросы, поэтому он вписывается в это. Это действительно личное предпочтение. –

+0

Благодарим за рекомендацию. – Tarik

0

Короче говоря, использование IQueryable намного лучше и позволяет дополнительно фильтровать возвращаемый IQueryable по пути, не имея фактически загруженного в память объекта или коллекции. В этом случае тип возврата является простым классом Клиента, и воздействие будет минимальным, но в случае коллекций вам настоятельно рекомендуется использовать IQueryable. Chris Sells показывает проблему более подробно here

0

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

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

Сценарий, в котором разница более полезна, - это если у вас есть метод, который возвращает несколько объектов. Отсроченное выполнение выражения означает, что вы загружаете только те объекты, которые вы используете. В случае, когда вам нужны только первые несколько объектов, остальные объекты не будут созданы.

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