如何设置实体框架核心迁移超时时间



我使用的是EF Core的最新版本(1.0.0)。我有一个迁移要在一个相当大的数据库上运行。

我运行

:

dotnet ef database update -c ApplicationDbContext

,得到:

超时过期。在完成之前经过的超时时间操作或服务器没有响应。

在连接字符串中,我显式地设置超时,如下所示:

连接超时= 150000

不幸的是,它没有帮助。我该怎么做呢?

您得到的错误信息是命令超时,而不是连接超时。

正如Pace在评论中提到的,自EF Core 2.0以来,您可以使用IDesignTimeDbContextFactory在设计时通过工具创建上下文时更改上下文的行为,例如在Migrations中发生的情况。

在您的项目中创建一个单独的类,实现IDesignTimeDbContextFactory接口,并使用DbContextoptionsBuilder来配置您想要的行为-在本例中,将命令超时值设置为600秒:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
namespace EFCoreSample.Model
{
    public class SampleContextFactory : IDesignTimeDbContextFactory<SampleContext>
    {
        public SampleContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<SampleContext>();
            optionsBuilder.UseSqlServer(@"Server=.;Database=db;Trusted_Connection=True;",
                opts => opts.CommandTimeout((int)TimeSpan.FromMinutes(10).TotalSeconds));
            return new SampleContext(optionsBuilder.Options);
        }
    }
}

确保您现有的DbContext有一个以DbContextOptions对象作为参数的构造函数:

public AdventureContext(DbContextOptions options) : base(options){}

当工具运行迁移时,它首先查找实现IDesignTimeDbContextFactory的类,如果找到,将使用它来配置上下文。运行时行为不受影响。

原答案不再适用

当使用EF命令时,没有办法在上下文上设置CommandTimeout。但是你可以在构造函数中全局地设置它,如果你不需要保留它,以后再把它删除:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext()
    {
        Database.SetCommandTimeout(150000);
    }
}

您只能通过在调用Migrations方法之前在上下文中设置超时来设置迁移的超时:

using (var context = new DispatchingDbContext(_configuration))
{
    context.Database.SetCommandTimeout(300);
    await context.Database.MigrateAsync().ConfigureAwait(false);
}

设置迁移超时ef .netcore

您也可以在数据库上下文类的构造函数中这样做。

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
    : base(options)
{
    Database.SetCommandTimeout(150000);
}

使用Entity Framework 6 (NOT CORE!),我使用DbMigrationsConfiguration.CommandTimeout属性为迁移设置了更长的超时时间。

:

在我的Global.asax.cs:

protected void Application_Start()
{
    DatabaseMigrationConfig.Register();
    //etc
}

My DatabaseMigrationConfig Class:

public class DatabaseMigrationConfig
{
    internal static void Register()
    {
        using (var context = new MyContext(Config.ConnectionStringMigrations))
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext,
                                        Migrations.Configuration>());
            context.Database.Initialize(false);
        }
    }
}

My Migrations.Configuration class:

using System.Data.Entity.Migrations;
internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        AutomaticMigrationDataLossAllowed = false;
        CommandTimeout = 360;// <----- 6 minute timeout!
    }
}

引用:

Migrations: Update-Database命令超时错误DbMigrationsConfiguration。CommandTimeout地产

请注意,我在迁移期间还使用了不同的连接字符串-用户具有比网站更高的权限,并且连接超时时间更长。参见这个问题-如何使用不同的连接字符串(但相同的数据库)进行迁移

您可以生成迁移SQL脚本,并使用以下命令直接在SQL服务器上运行:

dotnet ef migrations script [Baseline migration]

这样你就不受超时限制了。

更多信息可以在这里找到。

为Entity Framework 6生成这个脚本,使用:

Update-Database -Script -SourceMigration: [Baseline migration]

我通过从appsettings文件中读取连接字符串来改进Mike Brind的回答:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
namespace EFCoreSample.Model
{
    public class SampleContextFactory : IDesignTimeDbContextFactory<SampleContext>
    {
        public SampleContext CreateDbContext(string[] args)
        {
            var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
            var settingsFileName = $"appsettings.{env}.json";
            
            if (!File.Exists(settingsFileName))
            {
                settingsFileName = "appsettings.json";
            }
            
            var connectionString = new ConfigurationBuilder().AddJsonFile(settingsFileName).Build().GetConnectionString("GlobalConnection");
            var optionsBuilder = new DbContextOptionsBuilder<SampleContext>();
            optionsBuilder.UseSqlServer(connectionString,
                opts => opts.CommandTimeout((int)TimeSpan.FromMinutes(10).TotalSeconds));
            return new SampleContext(optionsBuilder.Options);
        }
    }
}

对Patrick Koorevaar的回答进行了小修改,以解释分层应用程序。json文件…

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
{
    public MyDbContext CreateDbContext(string[] args)
    {
        var builder = new ConfigurationBuilder();
        
        var settingsFileName = "appsettings.json";
        if (File.Exists(settingsFileName))
        {
            builder.AddJsonFile(settingsFileName);
        }
        
        var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
        var envSettingsFileName = $"appsettings.{env}.json";
        if (File.Exists(envSettingsFileName))
        {
            builder.AddJsonFile(envSettingsFileName);
        }
        
        var connectionString = builder.Build().GetConnectionString("MyConnString");
        var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
        optionsBuilder.UseSqlServer(connectionString,
            opts => opts.CommandTimeout((int)TimeSpan.FromMinutes(10).TotalSeconds));
        return new MyDbContext(optionsBuilder.Options);
    }
}

最新更新