【问题标题】:EntityFramework Code first migrations not running after deploying to AzureEntityFramework 代码首次迁移在部署到 Azure 后未运行
【发布时间】:2016-05-15 13:46:52
【问题描述】:

我正在使用代码优先迁移在 ASP.NET 中开发 Web 应用程序。它在本地运行良好,但在部署到 Azure 后,不会执行代码优先迁移。我已经逐步关注this tutorial 几次,但我无法发现我的设置有什么问题。以下是相关代码:

数据库上下文:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) {}

    public DbSet<BC_Instance> BiocloudInstances { get; set; }

    static ApplicationDbContext() {}

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        var conv = new AttributeToTableAnnotationConvention<SoftDeleteAttribute, string>(
           "SoftDeleteColumnName",
           (type, attributes) => attributes.Single().ColumnName);

        modelBuilder.Conventions.Add(conv);
    }
}

连接字符串:

(它在发布时被替换,但以防万一)

<add name="DefaultConnection" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=bcplatform2;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" /></connectionStrings>

代码优先迁移配置

internal sealed class Configuration : DbMigrationsConfiguration<bcplatform2.Models.ApplicationDbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(bcplatform2.Models.ApplicationDbContext context)
    {
        var userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(context));
        var roleManager = new ApplicationRoleManager(new RoleStore<ApplicationRole>(context));
        const string name = {name here};
        const string password = {pass here};
        const string adminRole = {role};
        string[] roles = new string[] { adminRole, ApplicationRole.DefaultRoleName };

        foreach (string role in roles)
        {
            if (!context.Roles.Any(r => r.Name == role))
            {
                roleManager.CreateAsync(new ApplicationRole(role));
            }
        }

        if (!context.Users.Any(u => u.UserName == name))
        {
            var user = new ApplicationUser { UserName = name, Email = name, credit = 10 };

            userManager.Create(user, password);
            userManager.AddToRole(user.Id, adminRole);
            userManager.SetLockoutEnabled(user.Id, false);
        }
    }
}

发布向导

已部署的 Web.config 中的实体框架部分

<entityFramework>
  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
    <parameters>
      <parameter value="mssqllocaldb" />
    </parameters>
  </defaultConnectionFactory>
  <providers>
    <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
  </providers>
  <contexts>
    <context type="bcplatform2.Models.ApplicationDbContext, bcplatform2">
      <databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[bcplatform2.Models.ApplicationDbContext, bcplatform2], [bcplatform2.Migrations.Configuration, bcplatform2]], EntityFramework, PublicKeyToken={token}">
        <parameters>
          <parameter value="DefaultConnection_DatabasePublish" />
        </parameters>
      </databaseInitializer>
    </context>
  </contexts>
</entityFramework>

已部署的 Web.config 中的连接字符串

<connectionStrings>
  <add name="DefaultConnection" connectionString="Data Source=tcp:{serverid}.database.windows.net,1433;Initial Catalog={dbid};User Id={user};Password={password}" providerName="System.Data.SqlClient" />
  <add name="DefaultConnection_DatabasePublish" connectionString="Data Source=tcp:{serverid}.database.windows.net,1433;Initial Catalog={dbid};User ID={user};Password={password}" providerName="System.Data.SqlClient" />
</connectionStrings>

【问题讨论】:

  • 您是否检查了部署的 web.config 文件?
  • 否,但与数据库的连接不是问题。问题是没有应用迁移,也没有为数据库播种。不过我会查一下
  • @ErikEJ 我修改了问题以包含此信息。确实,我不确定&lt;parameter value="mssqllocaldb" /&gt;&lt;databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2 是否正确,你知道它是否应该这样吗?
  • 是否需要将PublicKeyToken={token}放入databaseInitializer?检查此链接msdn.microsoft.com/en-us/data/jj556606.aspx
  • 尝试从“databaseInitializer”中删除“parameters”部分。或者检查 Azure 网站配置中是否存在连接字符串“DefaultConnection_DatabasePublish”。

标签: asp.net-mvc entity-framework azure ef-code-first entity-framework-migrations


【解决方案1】:

您可以在解决方案中更新您的 Web.config 文件

不必在“context”部分提供连接字符串,因为您已经在 ApplicationDbContext 构造函数中提供了它。

此外,使用此配置,您可以取消选中发布向导中的“执行代码先迁移”。

您的 EF 部分应与此类似(最重要的是“上下文”部分):

<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
  <parameters>
    <parameter value="mssqllocaldb" />
  </parameters>
</defaultConnectionFactory>
<providers>
  <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
<contexts>
  <context type="TestWebApp.Models.AppContext, TestWebApp">
    <databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[TestWebApp.Models.AppContext, TestWebApp], [TestWebApp.Migrations.Configuration, TestWebApp]], EntityFramework" />
  </context>
</contexts>

【讨论】:

    【解决方案2】:

    它不起作用,因为您可能在部署向导中创建/选择了其他连接。同样在部署的连接字符串中得到确认,您可以在其中看到两个连接字符串。

    第二个连接字符串也在 EF seciton 中被引用 -

    并且,在您使用第一个连接字符串的上下文中 - public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) {}

    在此处更改名称将解决您的问题。

    【讨论】:

    • 感谢@jitendra。这是有道理的。但是你知道我怎样才能摆脱这种“其他”联系吗?我从未打算创建一个,事实上它是在我相信的部署过程中为我创建的。我想将“DefaultConnection”用于开发和生产。
    • 尝试取消选中部署向导中的使用此连接字符串选项,因为您已经有一个。这可能会有所帮助。
    • 你能解决它吗?我很想听听反馈。
    【解决方案3】:

    如果您想对迁移过程进行更多控制,您可以在 Startup.Auth 中通过创建上下文并使用 DBMigrator() 类来处理迁移应用任何待处理的迁移:

    //Get the connection string
    var connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"];
    
    //Instanciate the sql connection string builder
    var builder = new System.Data.SqlClient.SqlConnectionStringBuilder(connectionString.ConnectionString);
    
    //Create your context
    var dbContext = new ApplicationDbContext(builder.ConnectionString);
    
    //Check for null (Handle issue here).
    if (dbContext == null) return;
    
    //Get your configuration and specify the target database
    var config = new Migrations.Configuration();
    config.TargetDatabase = new DbConnectionInfo(builder.ConnectionString, "System.Data.SqlClient");
    
    //Create the migrator using your config
    var mig = new DbMigrator(config);
    
    //Check for any pending migration to speed up the process and Update
    //The migration will be applied here each time the application is published on azure   
    if(mig.GetPendingMigrations().Any())mig.Update();
    

    虽然这可能无法直接解决您的问题,但它允许更多控制,您应该能够通过一些调试来查看迁移是否未应用。

    【讨论】:

      【解决方案4】:

      问题出在种子方法上:

      protected override void Seed(bcplatform2.Models.ApplicationDbContext context)
      {
          var userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(context));
          var roleManager = new ApplicationRoleManager(new RoleStore<ApplicationRole>(context));
          const string name = {name here};
          const string password = {pass here};
          const string adminRole = {role};
          string[] roles = new string[] { adminRole, ApplicationRole.DefaultRoleName };
      
          foreach (string role in roles)
          {
              if (!context.Roles.Any(r => r.Name == role))
              {
                  roleManager.CreateAsync(new ApplicationRole(role));
              }
          }
      
          if (!context.Users.Any(u => u.UserName == name))
          {
              var user = new ApplicationUser { UserName = name, Email = name, credit = 10 };
      
              userManager.Create(user, password);
              userManager.AddToRole(user.Id, adminRole);
              userManager.SetLockoutEnabled(user.Id, false);
          }
      }
      

      它没有完成,但在发布输出上没有显示任何错误,因此很难发现错误。我删除了种子方法并且迁移工作。

      避免将来出现类似问题的一些建议是不要使用发布向导中的“在运行时使用此连接字符串”和“执行代码优先迁移”选项。如果出现问题,输出不会总是显示错误,并且几乎无法控制 Web.config 的修改方式。

      相反,在发布之前替换 Web.config 中的连接字符串或相应地配置 Web.Debug.config 和 Web.Release.config。

      【讨论】:

      • 是的,但我不知道它有什么问题,因为相同的代码在“后期”成功完成,但在种子操作中失败
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多