Command Timeout with Entity Framework 4.1 Code First

后端 未结 5 1226
攒了一身酷
攒了一身酷 2021-01-01 10:06

How can I set the command timeout of a DbContext?

相关标签:
5条回答
  • 2021-01-01 10:12

    If you're using SqlServer, just add this to your connection string: "... Connect Timeout = x" Where x is the timeout in ms.

    0 讨论(0)
  • 2021-01-01 10:23

    I found this solution after another Google search. You can access the ObjectContext for a DbContext by casting this to an IObjectContextAdapter.

    From 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;
        }
    }
    
    0 讨论(0)
  • 2021-01-01 10:26

    I have had the same problem running EntityFramework v4.4 with CodeFirstStoredProc v2.2. Upgrading was not an option for me so I had to update the CodeFirstStoredProcs.cs file to take in a new nullable int parameter called "commandTimeout" into the following 3 methods as shown below.

    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 the method below, this is where a condition to check the parameter and apply the cmd.connectionTimeout value.

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

    I hope this help as I was looking around for help but found nothing, not until I realised that I could do so without updating versions of CodeFirstStoredProcs that forces me to update EntityFramework as well.

    0 讨论(0)
  • 2021-01-01 10:29

    Please try the following code before you execute any DB command. The following Code need 3/4 minute to execute. So, CommandTimeout set 300 (in seconds) before execution of the command.

    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 讨论(0)
  • 2021-01-01 10:34

    A better solution to this for later versions of Entity Framework is to use the DbContext.Database.CommandTimeout property. I think this came in with EF 6.

    0 讨论(0)
提交回复
热议问题