Возврат объекта IQueryable или Enumerated - PullRequest
4 голосов
/ 07 апреля 2010

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

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

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;
    }
}

Заранее спасибо.

Ответы [ 3 ]

4 голосов
/ 07 апреля 2010

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

Например, предположим, что у вашего 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 голосов
/ 07 апреля 2010

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

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

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

0 голосов
/ 07 апреля 2010

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

...