Установить время ожидания базы данных в Entity Framework

164

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

Я нашел myDb.Database.Connection.ConnectionTimeout, но это так readonly.

Как я могу установить время ожидания команды в Entity Framework 5 ?

Джеймс
источник
20
К вашему сведению, на EF6 Database.CommandTimeoutбольше не только для чтения
itho
2
@itsho Он говорил об этом Database.Connection.ConnectionTimeout. В любом случае, я бы сказал, что Database.CommandTimeoutэто правильно в случае, если ваш запрос истекает (исключение System.Data.Entity.Core.EntityCommandExecutionExceptionсодержит System.Data.SqlClient.SqlException: Timeout expired.).
Дэвид Ференци Рогожан,
2
Возможное дублирование тайм-аутов Entity Framework
Тим Полманн
1
Я предполагаю, что вы на самом деле не заботитесь о тайм-ауте СОЕДИНЕНИЯ, но вместо этого вы хотите настроить тайм-аут КОМАНДЫ.
Достойно7

Ответы:

199

Попробуйте это в вашем контексте:

public class MyDatabase : DbContext
{
    public MyDatabase ()
        : base(ContextHelper.CreateConnection("Connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 180;
    }
}

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

<connectionStrings>

<add name="AdventureWorksEntities"
connectionString="metadata=.\AdventureWorks.csdl|.\AdventureWorks.ssdl|.\AdventureWorks.msl;
provider=System.Data.SqlClient;provider connection string='Data Source=localhost;
Initial Catalog=AdventureWorks;Integrated Security=True;Connection Timeout=60;
multipleactiveresultsets=true'" providerName="System.Data.EntityClient" />

</connectionStrings>

Источник: Как: определить строку подключения

Лениэль Маккаферри
источник
1
Я бы порекомендовал использовать версию строки подключения, так как если вы пытаетесь получить доступ к ObjectContextэтому конструктору, иногда команды консоли PowerShell / NuGet будут сбои по кругу .
Кевин Горски
130
Тайм-аут соединения и CommandTimeout и две разные вещи. Параметр строки подключения «Время ожидания подключения» не влияет на время выполнения команды (CommandTimeout).
Клей Ленхарт
3
Моя проблема была немного другой. Я получил таймаут во время миграций. EF имеет аналогичное свойство для использования во время миграции: msdn.microsoft.com/en-us/library/…
Karsten
2
В зависимости от того, какую версию EF вы используете, посмотрите этот ответ, чтобы получить представление о различных API-интерфейсах о том, как указывать свойство CommandTimeout.
Джим Ахо
1
У меня не работает (Соединение против Команды не то же самое, что я подозреваю). Этот пост решил эту проблему, хотя stackoverflow.com/questions/6232633/entity-framework-timeouts
Jezbers
181

Ты можешь использовать DbContext.Database.CommandTimeout = 180;

Это довольно просто и не требуется приведение.

Ву Нгуен
источник
1
Очень полезно для нас, которые используют Fluent APIформу EF.
GoldBishop
20

Мой частичный контекст выглядит так:

public partial class MyContext : DbContext
{
    public MyContext (string ConnectionString)
        : base(ConnectionString)
    {
        this.SetCommandTimeOut(300);
    }

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

Я оставил SetCommandTimeOutобщедоступным, поэтому я изменяю только те процедуры, которые мне нужны (более 5 минут) вместо глобального таймаута.

Эрик Филипс
источник
9

В сгенерированном коде конструктора он должен вызвать OnContextCreated()

Я добавил этот частичный класс для решения проблемы:

partial class MyContext: ObjectContext
{
    partial void OnContextCreated()
    {
        this.CommandTimeout = 300;
    }
}
Оуэн
источник
8

Я расширил ответ Ронни беглой реализацией, чтобы вы могли использовать его так:

dm.Context.SetCommandTimeout(120).Database.SqlQuery...

public static class EF
{
    public static DbContext SetCommandTimeout(this DbContext db, TimeSpan? timeout)
    {
        ((IObjectContextAdapter)db).ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;

        return db;
    }

    public static DbContext SetCommandTimeout(this DbContext db, int seconds)
    {
        return db.SetCommandTimeout(TimeSpan.FromSeconds(seconds));
    } 
}
Timmerz
источник
8

Для базы данных сначала Aproach:

Мы все еще можем установить его в конструкторе, переопределив шаблон T4 ContextName.Context.tt следующим образом:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
    public <#=code.Escape(container)#>()
        : base("name=<#=container.Name#>")
    {
        Database.CommandTimeout = 180;
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
        this.Configuration.LazyLoadingEnabled = false;
<#
}

Database.CommandTimeout = 180; это резкое изменение.

Сгенерированный вывод:

public ContextName() : base("name=ContextName")
{
    Database.CommandTimeout = 180;
}

Если вы измените модель базы данных, этот шаблон останется, но сам класс будет обновлен.

Кристиан Голлхардт
источник
Есть ли способ указать время ожидания в шаблоне с помощью какого-либо файла конфигурации?
Шас
1
не уверен, что там что-то встроено (я не смог что-то найти). Но вместо System.Configuration.ConfigurationManager.AppSettings["keyname"]жесткого кода 180, вы можете использовать @shas
Christian Gollhardt
7

То же, что и другие ответы, но как метод расширения:

static class Extensions
{
    public static void SetCommandTimeout(this IObjectContextAdapter db, TimeSpan? timeout)
    {
        db.ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;
    }
}
Ронни Оверби
источник
и как я могу вызвать этот метод расширения?
Вандерсон Лопес
1

Я просто столкнулся с этой проблемой и решил ее, обновив файл конфигурации своего приложения. Для рассматриваемого соединения укажите «Connection Timeout = 60» (я использую Entity Framework версии 5.0.0.0)

Настройка ConnectionTimeout

Эндрю Берроу
источник
0

Вы можете использовать это просто:
dbContext.Database.SetCommandTimeout(300);

Хасан Мухаммед Саад
источник