Тайм-ауты Entity Framework

229

Я получаю таймауты с использованием Entity Framework (EF) при использовании импорта функции, для завершения которой требуется более 30 секунд. Я попробовал следующее и не смог решить эту проблему:

Я добавил Default Command Timeout=300000 в строку подключения в файле App.Config в проекте с файлом EDMX, как предлагается здесь.

Вот как выглядит моя строка подключения:

<add 
    name="MyEntityConnectionString" 
    connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|
       res://*/MyEntities.msl;
       provider=System.Data.SqlClient;provider connection string=&quot;
       Data Source=trekdevbox;Initial Catalog=StarTrekDatabase;
       Persist Security Info=True;User ID=JamesTKirk;Password=IsFriendsWithSpock;
       MultipleActiveResultSets=True;Default Command Timeout=300000;&quot;"
    providerName="System.Data.EntityClient" />

Я попытался установить CommandTimeout в моем репозитории прямо так:

private TrekEntities context = new TrekEntities();

public IEnumerable<TrekMatches> GetKirksFriends()
{
    this.context.CommandTimeout = 180;
    return this.context.GetKirksFriends();
}

Что еще я могу сделать, чтобы получить EF от тайм-аута? Это происходит только для очень больших наборов данных. Все работает отлично с небольшими наборами данных.

Вот одна из ошибок, которые я получаю:

System.Data.EntityCommandExecutionException: при выполнении определения команды произошла ошибка. Подробнее см. Внутреннее исключение. --- > System.Data.SqlClient.SqlException: время ожидания истекло. Период ожидания истекает до завершения операции или сервер не отвечает.


ОК. У меня это работает, и это глупо, что произошло. У меня была строка подключения с Default Command Timeout=300000, а CommandTimeout - 180. Когда я удалил строку Default Command Timeout из строки подключения, она сработала. Поэтому ответ заключается в том, чтобы вручную установить CommandTimeout в вашем репозитории на свой объект контекста следующим образом:

this.context.CommandTimeout = 180;

По-видимому, установка параметров таймаута в строке соединения не влияет на него.

  • 0
    Удалить & quot; из строки подключения
  • 0
    см. также stackoverflow.com/questions/4396833/sql-exception-with-net-4-ef
Показать ещё 3 комментария
Теги:
entity-framework
connection-string
entity-framework-4

6 ответов

409
Лучший ответ

Известна ошибка с указанием тайм-аута команды по умолчанию в строке подключения EF.

http://bugs.mysql.com/bug.php?id=56806

Удалите значение из строки подключения и установите его на самом объекте контекста данных. Это будет работать, если вы удалите конфликтующее значение из строки подключения.

Entity Framework Core 1.0:

this.context.Database.SetCommandTimeout(180);

Entity Framework 6:

this.context.Database.CommandTimeout = 180;

Entity Framework 5:

((IObjectContextAdapter)this.context).ObjectContext.CommandTimeout = 180;

Entity Framework 4 и ниже:

this.context.CommandTimeout = 180;
  • 5
    Как я могу добиться этого с помощью EDMX?
  • 0
    @iroel Файл модели EDMX не отображает эти свойства в контексте данных. Вам нужно получить доступ к свойству контекста данных, используя один из методов выше.
Показать ещё 13 комментариев
83

Если вы используете DbContext, используйте следующий конструктор для установки таймаута команды:

public class MyContext : DbContext
{
    public MyContext ()
    {
        var adapter = (IObjectContextAdapter)this;
        var objectContext = adapter.ObjectContext;
        objectContext.CommandTimeout = 1 * 60; // value in seconds
    }
}
  • 3
    @ErickPetru, так что вы можете легко изменить его на другое количество минут :), также я не был бы слишком удивлен, если бы компилятор оптимизировал это умножение!
  • 2
    @JoelVerhagen, не удивляйся. Вот хорошее объяснение того, когда происходит автоматическая оптимизация: stackoverflow.com/questions/160848/… . В этом случае, я предполагаю, что это даже произойдет (поскольку они являются двумя буквальными значениями), но, честно говоря, я думаю, что код немного странный в этом смысле.
Показать ещё 7 комментариев
32

Если вы используете DbContext и EF v6 +, вы также можете использовать:

this.context.Database.CommandTimeout = 180;
6

Обычно я обрабатываю свои операции в транзакции . Как я уже сказал, недостаточно установить тайм-аут командной строки, но для транзакции нужен конструктор с параметром таймаута. Я должен был установить оба значения времени ожидания для правильной работы.

int? prevto = uow.Context.Database.CommandTimeout;
uow.Context.Database.CommandTimeout = 900;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(900))) {
...
}

В конце функции я вернул время ожидания команды в предыдущее значение в предыдущем.

Использование EF6

1

Я знаю, что это очень старый поток, но EF еще не исправил это. Для людей, использующих автогенерированный DbContext, можно использовать следующий код для установки таймаута вручную.

public partial class SampleContext : DbContext
{
    public SampleContext()
        : base("name=SampleContext")
    {
        this.SetCommandTimeOut(180);
    }

    public void SetCommandTimeOut(int Timeout)
    {
        var objectContext = (this as IObjectContextAdapter).ObjectContext;
        objectContext.CommandTimeout = Timeout;
    }
1

Это то, что я финансирую. Может быть, это поможет кому-то:

Итак, идем:

Если вы используете LINQ с EF, ищите некоторые точные элементы, содержащиеся в списке, например:

await context.MyObject1.Include("MyObject2").Where(t => IdList.Contains(t.MyObjectId)).ToListAsync();

все идет нормально, пока IdList не содержит более одного идентификатора.

Проблема "тайм-аута" появляется, если список содержит только один идентификатор. Чтобы решить проблему, используйте условие проверки количества идентификаторов в IdList.

Пример:

if (IdList.Count == 1)
{
    result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.FirstOrDefault()==t. MyObjectId).ToListAsync();
}
else
{
    result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.Contains(t. MyObjectId)).ToListAsync();
}

Пояснение:

Просто попробуйте использовать Sql Profiler и проверьте оператор Select, сгенерированный Entity frameork....

Ещё вопросы

Сообщество Overcoder
Наверх
Меню