Command Timeout with Entity Framework 4.1 Code First
How can开发者_运维百科 I set the command timeout of a DbContext?
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;
}
}
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.
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();
}
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.
If you're using SqlServer, just add this to your connection string: "... Connect Timeout = x" Where x is the timeout in ms.
精彩评论