Как установить CommandTimeout для DbContext?
Я ищу способ установить CommandTimeout для DbContext. После поиска я нашел способ, поместив DbContext в ObjectContext и установив значение для свойства CommandTimeout объекта object.conf.
var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext;
Но мне нужно работать с DbContext.
Ответы
Ответ 1
Он будет работать с вашим методом.
Или подкласс (от msdn forum)
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;
}
}
Ответ 2
Это может вам помочь.
public class MyContext : DbContext
{
public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true)
{
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
}
}
Ответ 3
var ctx = new DbContext();
ctx.Database.CommandTimeout = 120;
Ответ 4
Я обнаружил, что изменение файла .tt работает для меня, поскольку я не потеряю это изменение позже:
Добавьте эту строку:
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
Сразу после создателя DbContext и перед конструкцией loader.IsLazy:
<#=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))
Затем он должен появиться в созданном Context.cs:
public MyEntities()
: base("name=MyEntities")
{
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
}
Ответ 5
Мне нравится подход к расширению:
public static class DbContextExtensions
{
public static void SetCommandTimeout(this ObjectContext dbContext,
int TimeOut)
{
dbContext.CommandTimeout = TimeOut;
}
}
а затем просто
((IObjectContextAdapter)cx).ObjectContext.SetCommandTimeout(300);
Ответ 6
Вот как я решил эту проблему при использовании 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;
}
}
}
У этого есть дополнительная функция: я не жестко кодирую тайм-аут команды по умолчанию. Вместо этого я загружаю его из параметров проекта, чтобы изменить значение в файле конфигурации. Как настроить и использовать настройки проекта не входит в объем этого ответа.
Я также не жестко кодирую строку подключения или имя строки подключения. Он уже перешел в конструктор сгенерированным классом контекста, поэтому нет смысла его жестко кодировать. Это ничего нового; файл EDMX уже генерирует для вас следующий конструктор, поэтому мы просто передаем значение.
public MyEntities()
: base("name=MyEntities")
{
}
(Это дает указание EF загрузить строку конфигурации с именем "MyEntities" из файла конфигурации.)
Я бросаю специальное исключение, если ObjectContext
всегда имеет значение null. Я не думаю, что это когда-либо будет, но это более значимо, чем получение NullReferenceException
.
Я сохраняю ObjectContext
в поле, чтобы я мог сделать свойство для доступа к нему, чтобы переопределить значение по умолчанию.
Изменение шаблона T4 контекста объекта
В обозревателе решений разверните файл EDMX, чтобы вы увидели шаблоны T4. Они имеют расширение .tt.
Дважды щелкните файл "MyModel.Context.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.Context.tt" под вашим EDMX файлом, вы увидите "MyModel.Context.cs". Это сгенерированный файл. Откройте его, и вы увидите, что теперь он наследует CustomDbContext
.
public partial class MyEntities : CustomDbContext
Это все, что нужно.
Вопросы
После изменения класса контекста от DbContext
до CustomDbContext
, Visual Studio даст вам сообщение об ошибке, если вы попытаетесь добавить новый класс контроллера MVC, используя "Контроллер с действиями и представлениями чтения/записи", используя Entity Framework ". Он скажет" Неподдерживаемый тип контекста". Чтобы обойти это, откройте сгенерированный класс "MyModel.Context.cs" и временно измените тип, наследуемый до DbContext
. После добавления нового контроллера вы можете изменить его на CustomDbContext
.
Ответ 7
Если это может помочь, это решение VB.Net:
Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext
objectContext.commandTimeout = connectionTimeout
Ответ 8
Я пришел сюда, чтобы найти пример установки тайм-аута для одной команды, а не такой глобальной настройки.
Я полагаю, что это, вероятно, поможет кому-то привести пример того, как я это достиг:
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();