Подтвердить что ты не робот

Как установить CommandTimeout для DbContext?

Я ищу способ установить CommandTimeout для DbContext. После поиска я нашел способ, поместив DbContext в ObjectContext и установив значение для свойства CommandTimeout объекта object.conf.

var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext;

Но мне нужно работать с DbContext.

4b9b3361

Ответ 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();