Ustaw limit czasu bazy danych w Entity Framework

164

Moje polecenie ciągle przekracza limit czasu, więc muszę zmienić domyślną wartość limitu czasu polecenia.

Znalazłem myDb.Database.Connection.ConnectionTimeout, ale to jest readonly.

Jak mogę ustawić limit czasu polecenia w Entity Framework 5 ?

James
źródło
20
FYI, na EF6, Database.CommandTimeoutnie jest już tylko do odczytu
itsho
2
@itsho, o którym mówił Database.Connection.ConnectionTimeout. W każdym razie powiedziałbym, że Database.CommandTimeoutjest to właściwe rozwiązanie w przypadku, gdy zapytanie przekracza limit czasu ( System.Data.Entity.Core.EntityCommandExecutionExceptionzawiera wyjątek System.Data.SqlClient.SqlException: Timeout expired.).
David Ferenczy Rogožan
2
Możliwy duplikat limitów
Tim Pohlmann,
1
Zakładam, że tak naprawdę nie obchodzi Cię limit czasu POŁĄCZENIA, ale zamiast tego chcesz dostosować limit czasu POLECENIA.
Worthy 7

Odpowiedzi:

199

Wypróbuj to w swoim kontekście:

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

Jeśli chcesz zdefiniować limit czasu w ciągu połączenia, użyj Connection Timeoutparametru podobnego do następujących parametrów połączenia:

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

Źródło: instrukcje: definiowanie parametrów połączenia

Leniel Maccaferri
źródło
1
Polecam użycie wersji parametrów połączenia, tak jakbyś próbował uzyskać dostęp do ObjectContexttego konstruktora, czasami polecenia konsoli PowerShell / NuGet zawodzą w cykliczny sposób .
Kevin Gorski
130
Connection Timeout i CommandTimeout oraz dwie oddzielne rzeczy. Ustawienie parametrów połączenia, Limit czasu połączenia, nie ma wpływu na czas działania polecenia (CommandTimeout).
Clay Lenhart
3
Mój problem był trochę inny. Wystąpił limit czasu podczas migracji. EF ma podobną właściwość do ustawienia do użycia podczas migracji: msdn.microsoft.com/en-us/library/…
Karsten
2
W zależności od używanej wersji EF, zobacz tę odpowiedź, aby poznać różne interfejsy API w sposobie określania właściwości CommandTimeout.
Jim Aho
1
Nie działa dla mnie (Podejrzewam, że połączenie vs polecenie nie jest tym samym). Ten post rozwiązał to przez stackoverflow.com/questions/6232633/entity-framework-timeouts
Jezbers
181

Możesz użyć DbContext.Database.CommandTimeout = 180;

To całkiem proste i nie wymaga obsady.

Vu Nguyen
źródło
1
Bardzo przydatne dla nas korzystających z Fluent APIformy EF.
GoldBishop
20

Mój częściowy kontekst wygląda tak:

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

Zostawiłem SetCommandTimeOutpubliczne, więc tylko procedury, których potrzebuję, zajmują dużo czasu (ponad 5 minut), modyfikuję zamiast globalnego limitu czasu.

Erik Philips
źródło
9

W wygenerowanym kodzie konstruktora powinien wywołać OnContextCreated()

Dodałem tę częściową klasę, aby rozwiązać problem:

partial class MyContext: ObjectContext
{
    partial void OnContextCreated()
    {
        this.CommandTimeout = 300;
    }
}
piekarnik
źródło
8

Rozszerzyłem odpowiedź Ronniego o płynną implementację, abyś mógł z niej korzystać w następujący sposób:

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
źródło
8

Dla bazy danych pierwsze podejście:

Nadal możemy ustawić go w konstruktorze, nadpisując szablon ContextName.Context.tt T4 w ten sposób:

<#=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; to ostra zmiana.

Wygenerowane dane wyjściowe są następujące:

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

Jeśli zmienisz model bazy danych, ten szablon pozostanie, ale aktualna klasa zostanie zaktualizowana.

Christian Gollhardt
źródło
Czy istnieje sposób, aby określić limit czasu w szablonie za pomocą jakiegoś pliku konfiguracyjnego?
odbędzie się
1
nie jestem pewien, czy coś jest wbudowane (nie mogłem czegoś znaleźć). Ale zamiast zakodowania 180 na System.Configuration.ConfigurationManager.AppSettings["keyname"]sztywno , możesz użyć @shas
Christian Gollhardt
7

To samo, co inne odpowiedzi, ale jako metoda rozszerzenia:

static class Extensions
{
    public static void SetCommandTimeout(this IObjectContextAdapter db, TimeSpan? timeout)
    {
        db.ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;
    }
}
Ronnie Overby
źródło
i jak mam wywołać tę metodę rozszerzenia?
Wanderson López
1

Właśnie natknąłem się na ten problem i rozwiązałem go, aktualizując plik konfiguracyjny aplikacji. W przypadku danego połączenia określ „Limit czasu połączenia = 60” (używam platformy jednostek w wersji 5.0.0.0)

Ustawienie ConnectionTimeout

Andrew Burrow
źródło
0

Możesz użyć tego prostego:
dbContext.Database.SetCommandTimeout(300);

Hassan Muhammad Saad
źródło