Legen Sie das Datenbankzeitlimit in Entity Framework fest


164

Mein Befehl läuft ständig ab, daher muss ich den Standardwert für das Zeitlimit für Befehle ändern.

Ich habe gefunden myDb.Database.Connection.ConnectionTimeout, aber es ist readonly.

Wie kann ich das Befehlszeitlimit in Entity Framework 5 festlegen ?


20
Zu Ihrer Information, auf EF6, Database.CommandTimeoutist nicht mehr schreibgeschützt
itsho

2
@itsho Er sprach über Database.Connection.ConnectionTimeout. Wie auch immer, ich würde sagen, dass dies Database.CommandTimeoutdas Richtige ist, wenn Ihre Abfrage eine Zeitüberschreitung aufweist (Ausnahme System.Data.Entity.Core.EntityCommandExecutionExceptionenthalten System.Data.SqlClient.SqlException: Timeout expired.).
David Ferenczy Rogožan

2
Mögliches Duplikat von Entity Framework Timeouts
Tim Pohlmann

1
Ich gehe davon aus, dass Ihnen das CONNECTION-Timeout eigentlich egal ist, sondern dass Sie das COMMAND-Timeout anpassen möchten.
Worthy7

Antworten:


199

Versuchen Sie dies in Ihrem Kontext:

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

Wenn Sie das Zeitlimit in der Verbindungszeichenfolge definieren möchten, verwenden Sie den Connection TimeoutParameter wie in der folgenden Verbindungszeichenfolge:

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

Quelle: Gewusst wie: Definieren Sie die Verbindungszeichenfolge


1
Ich würde empfehlen, die Verbindungszeichenfolgenversion so zu verwenden, als ob Sie versuchen, ObjectContextin diesem Konstruktor auf die zuzugreifen. Manchmal schlagen die PowerShell / NuGet-Konsolenbefehle zirkulär fehl .
Kevin Gorski

130
Verbindungs-Timeout und CommandTimeout und zwei verschiedene Dinge. Die Einstellung für die Verbindungszeichenfolge "Verbindungszeitlimit" hat keinen Einfluss auf die Ausführungsdauer des Befehls (CommandTimeout).
Clay Lenhart

3
Mein Problem war ein bisschen anders. Ich habe während der Migrationen eine Auszeit bekommen. EF hat eine ähnliche Eigenschaft, die für die Verwendung während Migrationen festgelegt werden muss: msdn.microsoft.com/en-us/library/…
Karsten

2
Je nachdem, welche Version von EF Sie verwenden, finden Sie in dieser Antwort ein Gefühl für die verschiedenen APIs beim Angeben der CommandTimeout-Eigenschaft.
Jim Aho

1
Funktioniert bei mir nicht (Verbindung gegen Befehl ist nicht dasselbe, was ich vermute). Dieser Beitrag löste es durch stackoverflow.com/questions/6232633/entity-framework-timeouts
Jezbers

181

Sie können verwenden DbContext.Database.CommandTimeout = 180;

Es ist ziemlich einfach und keine Besetzung erforderlich.


1
Sehr nützlich für uns, die Fluent APIForm von EF verwenden.
GoldBishop

20

Mein Teilkontext sieht aus wie:

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

Ich habe die SetCommandTimeOutÖffentlichkeit verlassen, sodass nur die Routinen, die ich für eine lange Zeit (mehr als 5 Minuten) benötige, anstelle einer globalen Zeitüberschreitung geändert werden.


9

Im generierten Konstruktorcode sollte es aufrufen OnContextCreated()

Ich habe diese Teilklasse hinzugefügt, um das Problem zu lösen:

partial class MyContext: ObjectContext
{
    partial void OnContextCreated()
    {
        this.CommandTimeout = 300;
    }
}

8

Ich habe Ronnies Antwort mit einer fließenden Implementierung erweitert, damit Sie sie folgendermaßen verwenden können:

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

Für die Datenbank zuerst Ansatz:

Wir können es weiterhin in einem Konstruktor festlegen , indem wir die ContextName.Context.tt T4-Vorlage folgendermaßen überschreiben :

<#=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; ist die akute Veränderung.

Die generierte Ausgabe lautet wie folgt:

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

Wenn Sie Ihr Datenbankmodell ändern, bleibt diese Vorlage erhalten, die aktuelle Klasse wird jedoch aktualisiert.


Gibt es eine Möglichkeit, das Zeitlimit in der Vorlage mithilfe einer Konfigurationsdatei anzugeben?
Shas

1
Ich bin mir nicht sicher, ob etwas eingebaut ist (ich konnte nichts finden). Aber anstatt 180 fest zu codieren, können Sie System.Configuration.ConfigurationManager.AppSettings["keyname"]@shas
Christian Gollhardt

7

Wie andere Antworten, jedoch als Erweiterungsmethode:

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

und wie nenne ich diese Erweiterungsmethode?
Wanderson López

1

Ich bin gerade auf dieses Problem gestoßen und habe es durch Aktualisieren meiner Anwendungskonfigurationsdatei behoben. Geben Sie für die betreffende Verbindung "Verbindungszeitlimit = 60" an (ich verwende das Entity Framework Version 5.0.0.0).

ConnectionTimeout-Einstellung


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.