webentwicklung-frage-antwort-db.com.de

Befehlszeitüberschreitung mit Entity Framework 4.1 Code First

Wie kann ich das Befehlszeitlimit eines DbContext festlegen?

31
MikeWyatt

Ich habe diese Lösung nach einer anderen Google-Suche gefunden. Sie können auf den ObjectContext für einen DbContext zugreifen, indem Sie this in einen IObjectContextAdapter umwandeln.

Von http://social.msdn.Microsoft.com/Forums/en-ZA/adodotnetentityframework/thread/6fe91a64-0208-4ab8-8667-d061af340994 :

public class MyContext : DbContext
{
    public MyContext ()
        : base(ContextHelper.CreateConnection("my connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
    }
}
74
MikeWyatt

Eine bessere Lösung für spätere Versionen von Entity Framework ist die Verwendung der Eigenschaft DbContext.Database.CommandTimeout. Ich denke, das kam mit EF 6.

7
Josh Gallagher

Bitte versuchen Sie den folgenden Code, bevor Sie einen DB-Befehl ausführen. Der folgende Code benötigt zur Ausführung 3/4 Minuten. Also, CommandTimeout setze 300 (in Sekunden) vor Ausführung des Befehls.

public List<CollectionEfficiencyByUnitOfficeSummary> ReadCollectionEfficiencyByUnitOfficeSummary(string yearMonth, string locationCode, string reportType)
        {
            ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.CommandTimeout = 300;
            return context.CollectionEfficiencyByUnitOfficeSummary(yearMonth, locationCode, reportType).ToList();
        }
0

Ich hatte das gleiche Problem beim Ausführen von EntityFramework v4.4 mit CodeFirstStoredProc v2.2. Das Aktualisieren war für mich keine Option, daher musste ich die CodeFirstStoredProcs.cs-Datei aktualisieren, um den neuen nullbaren int-Parameter "commandTimeout" in die folgenden drei Methoden zu übernehmen (siehe unten).

public static ResultsList CallStoredProc<T>(this DbContext context, StoredProc<T> procedure, T data, int? commandTimeout = null)
    {
        IEnumerable<SqlParameter> parms = procedure.Parameters(data);
        ResultsList results = context.ReadFromStoredProc(procedure.fullname, parms, commandTimeout, procedure.returntypes);
        procedure.ProcessOutputParms(parms, data);
        return results ?? new ResultsList();
    }

public static ResultsList CallStoredProc(this DbContext context, StoredProc procedure, IEnumerable<SqlParameter> parms = null, int? commandTimeout = null)
    {
        ResultsList results = context.ReadFromStoredProc(procedure.fullname, parms, commandTimeout, procedure.returntypes);
        return results ?? new ResultsList();
    }

In der folgenden Methode ist dies eine Bedingung, um den Parameter zu überprüfen und den Wert cmd.connectionTimeout anzuwenden.

internal static ResultsList ReadFromStoredProc(this DbContext context,
        String procname,
        IEnumerable<SqlParameter> parms = null,
        int? commandTimeout = null,
        params Type[] outputtypes)
    {
        // create our output set object
        ResultsList results = new ResultsList();

        // ensure that we have a type list, even if it's empty
        IEnumerator currenttype = (null == outputtypes) ?
            new Type[0].GetEnumerator() :
            outputtypes.GetEnumerator();

        // handle to the database connection object
        var connection = (SqlConnection)context.Database.Connection;
        try
        {
            // open the connect for use and create a command object
            connection.Open();
            using (var cmd = connection.CreateCommand())
            {
                // command to execute is our stored procedure
                cmd.CommandText = procname;
                cmd.CommandType = System.Data.CommandType.StoredProcedure;

                if (commandTimeout.HasValue)
                {
                    cmd.CommandTimeout = commandTimeout.Value;
                }

                // move parameters to command object
                if (null != parms)
                    foreach (SqlParameter p in parms)
                        cmd.Parameters.Add(p);
                //    foreach (ParameterHolder p in parms)
                //        cmd.Parameters.Add(p.toParameter(cmd));

                // Do It! This actually makes the database call
                var reader = cmd.ExecuteReader();

                // get the type we're expecting for the first result. If no types specified,
                // ignore all results
                if (currenttype.MoveNext())
                {
                    // process results - repeat this loop for each result set returned by the stored proc
                    // for which we have a result type specified
                    do
                    {
                        // get properties to save for the current destination type
                        PropertyInfo[] props = ((Type)currenttype.Current).GetMappedProperties();

                        // create a destination for our results
                        List<object> current = new List<object>();

                        // process the result set
                        while (reader.Read())
                        {
                            // create an object to hold this result
                            object item = ((Type)currenttype.Current).GetConstructor(System.Type.EmptyTypes).Invoke(new object[0]);

                            // copy data elements by parameter name from result to destination object
                            reader.ReadRecord(item, props);

                            // add newly populated item to our output list
                            current.Add(item);
                        }

                        // add this result set to our return list
                        results.Add(current);
                    }
                    while (reader.NextResult() && currenttype.MoveNext());
                }
                // close up the reader, we're done saving results
                reader.Close();
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Error reading from stored proc " + procname + ": " + ex.Message, ex);
        }
        finally
        {
            connection.Close();
        }

        return results;
    }
}

Ich hoffe, dass diese Hilfe, als ich mich nach Hilfe umsah, aber nichts fand, erst als ich merkte, dass ich dies tun konnte, ohne Versionen von CodeFirstStoredProcs zu aktualisieren, zwingt mich, auch EntityFramework zu aktualisieren.

0
InitialV