Встановіть час очікування бази даних в Entity Framework


164

Моя команда зберігає час, тому мені потрібно змінити значення тайм-ауту команди за замовчуванням.

Я знайшов myDb.Database.Connection.ConnectionTimeout, але це readonly.

Як я можу встановити тайм-аут команди в Entity Framework 5 ?


20
FYI, на EF6, Database.CommandTimeoutбільше не
доступний

2
@itsho Він говорив Database.Connection.ConnectionTimeout. У будь-якому разі, я б сказав, що Database.CommandTimeoutце правильна річ, якщо ваш запит - це тайм-аут (виняток, System.Data.Entity.Core.EntityCommandExecutionExceptionщо містить System.Data.SqlClient.SqlException: Timeout expired.).
David Ferenczy Rogožan

2
Можливий дублікат тайм-аутів Framework Entity
Тім Польман

1
Я припускаю, що ви насправді не турбуєтесь про час очікування підключення, але натомість ви хочете скорегувати час очікування COMMAND.
Варто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
Це не працює для мене (Connection vs Command не є тим самим, що я підозрюю). Це повідомлення вирішив його хоча 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));
    } 
}

8

Перший підхід до бази даних:

Ми все ще можемо встановити його в конструкторі, замінивши шаблон ContextName.Context.tt T4 таким чином:

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

Якщо ви зміните модель бази даних, цей шаблон залишається, але власне клас буде оновлений.


Чи можливо ми можемо вказати тайм-аут у шаблоні за допомогою якогось конфігураційного файла.?
shas

1
не впевнений, чи є щось вбудований (я не зміг щось знайти). Але замість жорсткого кодування 180, ви можете використовувати System.Configuration.ConfigurationManager.AppSettings["keyname"]@shas
Крістіан Голлхардт

7

Те саме, що й інші відповіді, але як метод розширення:

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

і як мені викликати цей метод розширення?
Вандерсон Лопес

1

Щойно я зіткнувся з цією проблемою і вирішив її, оновивши файл конфігурації програми. Для питання про з'єднання вкажіть "Час очікування підключення = 60" (я використовую сутність фреймворку версії 5.0.0.0)

Налаштування ConnectionTimeout


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.