Как установить CommandTimeout для DbContext?
Я ищу способ установить CommandTimeout для DbContext. После поиска я нашел способ, приведя DbContext в ObjectContext и установив значение для свойства CommandTimeout objectContext.
var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext;
но я должен работать с DbContext.
8 ответов
Он будет работать с вашим методом.
или подкласс (от форум msdn)
public class YourContext : DbContext
{
public YourContext()
: base("YourConnectionString")
{
// Get the ObjectContext related to this DbContext
var objectContext = (this as IObjectContextAdapter).ObjectContext;
// Sets the command timeout for all the commands
objectContext.CommandTimeout = 120;
}
}
Это может помочь вам.
public class MyContext : DbContext
{
public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true)
{
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
}
}
Я считаю, что изменение .TT файл работает для меня, как я не теряю изменения позже:
добавьте следующую строку:
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
сразу после создателя DbContext и до !погрузчик.IsLazy construct:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
<#
if (!loader.IsLazyLoadingEnabled(container))
затем он должен появиться в созданный контекст.cs:
public MyEntities()
: base("name=MyEntities")
{
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
}
мне нравится подход расширения:
public static class DbContextExtensions
{
public static void SetCommandTimeout(this ObjectContext dbContext,
int TimeOut)
{
dbContext.CommandTimeout = TimeOut;
}
}
и просто
((IObjectContextAdapter)cx).ObjectContext.SetCommandTimeout(300);
вот как я решил эту проблему при использовании файла EDMX. Это решение изменяет шаблон T4 по умолчанию, чтобы сгенерированный класс наследовался от пользовательского класса DbContext, который задает тайм-аут команды по умолчанию и свойство для его изменения.
я использую Visual Studio 2012 и EF 5.0. Ваш опыт может отличаться от других версий.
создайте пользовательский класс DbContext
public class CustomDbContext : DbContext
{
ObjectContext _objectContext;
public CustomDbContext( string nameOrConnectionString )
: base( nameOrConnectionString )
{
var adapter = (( IObjectContextAdapter) this);
_objectContext = adapter.ObjectContext;
if ( _objectContext == null )
{
throw new Exception( "ObjectContext is null." );
}
_objectContext.CommandTimeout = Settings.Default.DefaultCommandTimeoutSeconds;
}
public int? CommandTimeout
{
get
{
return _objectContext.CommandTimeout;
}
set
{
_objectContext.CommandTimeout = value;
}
}
}
это имеет необязательную функцию: я не жестко кодирую тайм-аут команды по умолчанию. Вместо этого я загружаю его из настроек проекта, чтобы изменить значение в файле конфигурации. Как настроить и использовать параметры проекта не входит в область этого ответа.
Я также не жестко кодирую строку подключения или имя строки подключения. Он уже передан в конструктор сгенерированным классом context, поэтому нет смысла жестко кодировать его здесь. Это ничего нового; файл EDMX уже генерирует следующий конструктор для вас, поэтому мы просто передаем ценность.
public MyEntities()
: base("name=MyEntities")
{
}
(это указывает EF загрузить строку подключения с именем "MyEntities" из файла конфигурации.)
Я бросаю пользовательское исключение, если ObjectContext
всегда равно null. Я не думаю, что это когда-нибудь будет, но это более значимо, чем получить NullReferenceException
.
Я храню ObjectContext
в поле, чтобы я мог сделать свойство для доступа к нему, чтобы переопределить значение по умолчанию.
изменение контекста сущности T4 шаблон
в обозревателе решений разверните файл EDMX, чтобы увидеть шаблоны T4. У них есть .расширение tt.
дважды щелкните "MyModel.Контекст.TT " файл, чтобы открыть его. Вокруг строки 57 вы должны увидеть следующее:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
эта строка шаблона генерирует определение класса вашего класса "MyEntities", который наследует DbContext.
измените строку так, чтобы созданный класс наследовал CustomDbContext, вместо этого:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : CustomDbContext
как только вы сохраните этот файл, он должен регенерировать класс. Если нет, вы можете щелкнуть правой кнопкой мыши файл EDMX и выбрать "запустить пользовательский инструмент". Если развернуть " MyModel.Контекст.TT "файл под файлом EDMX, вы увидите" MyModel.Контекст.цезий." Это сгенерированный файл. Откройте его, и вы увидите, что он теперь наследует CustomDbContext
.
public partial class MyEntities : CustomDbContext
вот и все.
вопросы
после изменения контекста класса DbContext
to CustomDbContext
, Visual Studio выдаст вам ошибку, если вы попытаетесь добавить новый класс контроллера MVC, используя шаблон "контроллер с действиями чтения/записи и представлениями, используя Entity Framework". Он скажет: "неподдерживаемый тип контекста.". Чтобы обойти это, откройте сгенерированную " MyModel.Контекст.cs " класс, и временно изменить тип, который он наследует обратно в DbContext
. После добавления нового контроллера вы можете изменить его на CustomDbContext
.
Если это может помочь, это VB.Net решение:
Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext
objectContext.commandTimeout = connectionTimeout
Я пришел сюда в поисках примера установки тайм-аута для одной команды, а не такой глобальной настройки.
Я полагаю, что это, вероятно, поможет кому-то иметь пример того, как я достиг этого:
var sqlCmd = new SqlCommand(sql, context.Database.Connection as SqlConnection);
sqlCmd.Parameters.Add(idParam);
sqlCmd.CommandTimeout = 90;
if (sqlCmd.Connection.State == System.Data.ConnectionState.Closed)
{
sqlCmd.Connection.Open();
}
sqlCmd.ExecuteNonQuery();
sqlCmd.Connection.Close();