Истекло время ожидания запросов EF Linq, но те же запросы менее 1 секунды на SSMS

сначала я попробовал ARITHABORT OFF на SSMS это все еще менее 1 секунды.

я использую EntityFrameWork: 6.1.3 и Azure Sql S1 tier (я попробую с уровнем 3 и дам вам знать, если что-то изменится.)

Я использую EF Profiler для получения сгенерированного sql из linq. Я запросил все linqs, которые я поделился, все они меньше 1 секунды на SSMS.

у меня есть 3 миллиона recods на таблице AuditLog. Один клиент с ID 3 имеет 170k записывает другого клиента с ID 35 имеет 125 записей. Я сведу код к минимуму.

Модель AuditLog:

 public class AuditLog
  {
    public long? CustomerId { get; set; }

    [ForeignKey("CustomerId")]
    public virtual CustomerSummary Customer { get; set; }

    [Required]
    [Index]
     public DateTime CreatedDate { get; set; }
  }

первый запрос:

 if (customer != null)
    {
      var customerId = customer.Id;
      var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
    }

если я попытаюсь с клиентом, у которого есть 170k строк, он дает исключение тайм-аута. Если я попробую с клиентом, у которого 125 записей, это нормально.

Второй Запрос: то же самое с первым, я просто включаю клиентов.

if (customer != null)
   {
      var customerId = customer.Id;
      var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
    }

результат противоположен первому запросу. если я попробую с клиентом, который имеет 170k строк, все в порядке. Если я попытаюсь с клиентом,у которого есть 125 записей, он дает исключение тайм-аута.

третий запрос: это то же самое с первым запросом, но я соответствую long? о том, где для customerId.

 if (customer != null)
    {
      long? customerId = customer.Id;
      var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
    }

результат противоположен первому запросу. если я попробую с клиентом, у которого есть 170k строк, все в порядке. Если я попытаюсь с клиентом,у которого есть 125 записей, он дает исключение тайм-аута.

четвертый вопрос: это то же самое со вторым запросом, но я матч long? о том, где для customerId.

 if (customer != null)
    {
      long? customerId = customer.Id;
      var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
    }

результат противоположен второму запросу. если я попробую с клиентом, у которого есть 170k строк, он дает исключение тайм-аута. Если я попробую с клиентом, у которого 125 записей, это нормально.

я совсем запуталась. Почему внутреннее соединение или изменение параметра соответствуют long? меняются результаты ? И почему это все запросы выполняются под 1 сек на SSMS и дают ошибку на EF linq ?

ошибка:

{System.Данные.В sqlclient.SqlException (0x80131904): истекло время ожидания. Время ожидания истекло до завершения операции или сервер не отвечает. ---> Система.ComponentModel.Win32Exception (0x80004005): тайм-аут операции ожидания на Система.Данные.В sqlclient.Объект sqlconnection.OnError (исключение SqlException, Boolean breakConnection, действие ' 1 wrapCloseInAction)

обновление (19/04/2016):

после Иван Стоев предложение на комментарии.

вы пробовали (только ради теста), используя hardcoded 3 и 35 вместо customerId переменной?

Я не получил никакой ошибки, и запросы самые быстрые, как на SSMS.

обновление (20/04/2016): реальная проблема Нюхают Параметр. Когда я включил или изменил параметр на nullable, на самом деле я создал другие запросы и другой запрос планировавший. Я создал некоторые планы с клиентом, у которого есть 125 записей, а другие-с клиентом, у которого есть 170k записей этих 4 запросов. Вот почему я получил разные результаты.

1 ответов


то, что вы испытываете, является результатом так называемого Проблема Нюхания Параметров. До сих пор я не знаю простого общего решения, поэтому обычно предлагаю обходной путь, устраняя некоторые параметры SQL-запроса, вручную связывая постоянные значения внутри выражений, как в EntityFramework LINQ query count завершается ошибкой, но запрос возвращает результат. Как оптимизировать запрос LINQ?.

для вашего сценария я бы предложил следующее пользовательское расширение метод:

public static class QueryableExtensions
{
    public static IQueryable<T> WhereEquals<T, TValue>(this IQueryable<T> source, Expression<Func<T, TValue>> selector, TValue value)
    {
        var predicate = Expression.Lambda<Func<T, bool>>(
            Expression.Equal(selector.Body, Expression.Constant(value)),
            selector.Parameters);
        return source.Where(predicate);
    }
}

а затем обновите свой фрагмент следующим образом

if (customer != null)
{
    var result= Dbset.WhereEquals(x => x.CustomerId.Value, customer.Id)
        .OrderByDescending(x => x.CreatedDate)
        .Skip(0).Take(25)
        .Include(x => x.Customer)
        .ToList();
}