How can I set the command timeout of a DbContext?
If you're using SqlServer, just add this to your connection string: "... Connect Timeout = x" Where x is the timeout in ms.
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;
}
}
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.
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();
}
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.