2017-10-14 42 views
0

MVC身份实体框架模型似乎被打破,阻止了模型更新。看来使用IdentityDbContext创建的实体框架模型无法更新。MVC身份实体框架模型更新失败 - “已经是对象”错误

我正在使用MVC Identity和EF,生产数据库以及开发数据库。该设置是标准的 - 一个项目 - 模型,EF配置,DbSets和EF类。要创建开发数据库,​​我有一个简单的程序列在下面。很长一段时间我没有任何问题使用这个基本配置。但是在转移到MVC Identity之后,我现在无法通过向模型添加新类来更新开发数据库。用普通的DbContext替换对IdentityDbContext的引用可以消除错误。不知道我做错了什么。

不确定这是否相关,但模型中的许多实体从BaseEF类继承以包含公共字段。

模型和CREATEDB都使用EF 6.0.0.0:

<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, 
      Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> 

我收到以下错误:

(1)如果我删除dev的数据库,并运行CREATEDB程序,我得到的错误,“已经有一个名为数据库中的活动的对象”。 (2)如果我允许程序删除数据库,则会发生支持数据库的模型已更改的错误。

我已经尝试添加和删除模型项目中的迁移没有任何成功。

namespace AzureV1_CreateTestDB 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     createDb(true); 
    } 

    public static void createDb(bool deleteDatabase) 
    { 
     IdentityEFContext dbContext = new IdentityEFContext(); 

     if (System.Configuration.ConfigurationManager.ConnectionStrings["IdentityEFContext"].ConnectionString.Contains("EFUpdatetest1")) 
     { 
     if (dbContext.Database.Exists()) 
     { 
      if (deleteDatabase) 
      { 
      // The following line throws this error: 
      // System.InvalidOperationException: 'The model backing the 'IdentityEFContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).' 

      dbContext.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction 
      , string.Format("ALTER DATABASE {0} SET SINGLE_USER WITH ROLLBACK IMMEDIATE", dbContext.Database.Connection.Database)); 

      dbContext.Database.Delete(); 
      } 
     } 

     initDBContext(dbContext); 
     System.Data.Entity.Core.Objects.ObjectContext oContext = ((IObjectContextAdapter)dbContext).ObjectContext; 

     if (System.Configuration.ConfigurationManager.ConnectionStrings["IdentityEFContext"].ConnectionString.Contains("EFUpdatetest1")) 
     { 
      ExecuteSql(oContext, "ALTER DATABASE EFUpdatetest1 SET ALLOW_SNAPSHOT_ISOLATION ON"); 
      ExecuteSql(oContext, "ALTER DATABASE EFUpdatetest1 SET READ_COMMITTED_SNAPSHOT ON"); 
     } 

     // insert data 
     InsertData(dbContext); 

     closeDBContext(dbContext); 

     MessageBox.Show("Database successfully created"); 
     } 
    } 

    public static void initDBContext(IdentityEFContext dbContext) 
    { 
     // The following line throws the error: 
     // System.Data.SqlClient.SqlException: 'There is already an object named 'Activities' in the database.' 

     while (((IObjectContextAdapter)dbContext).ObjectContext.Connection.State.ToString() != "Open") 
     { 
     ((IObjectContextAdapter)dbContext).ObjectContext.Connection.Open(); 
     } 
    } 
    } 
} 
// connectionString in createDb 

<connectionStrings> 
    <add name="IdentityEFContext" 
     providerName="System.Data.SqlClient" 
     connectionString="Server=localhost; Integrated Security=False; Database=EFUpdatetest1; User Id=dbtest; Password=Hello.123" /> 
</connectionStrings> 

的EF配置信息是如下::

// EntityContext.cs

using Microsoft.AspNet.Identity.EntityFramework; 
using Models; 
using System.Data.Entity; 
using System.Data.Entity.Migrations; 

namespace DataAccess 
{ 
    //public class IdentityEFContext : DbContext /* this works */ 
    public class IdentityEFContext : IdentityDbContext<User> 
    { 
    public IdentityEFContext() : base("IdentityEFContext") { } 

    static IdentityEFContext() 
    { 
     Database.SetInitializer<IdentityEFContext>(new IdentityEFInit()); 
    } 

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

    public DbSet<Activity> Activities { get; set; } 
    ... 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.Configurations.Add(new ActivityConfig()); 
     ... 
    } 
    } 

    //public class IdentityEFInit : DropCreateDatabaseIfModelChanges<IdentityEFContext> 
    public class IdentityEFInit : CreateDatabaseIfNotExists<IdentityEFContext> 
    { 
    protected override void Seed(IdentityEFContext context) 
    { 
     PerformInitialSetup(context); 
     base.Seed(context); 
    } 

    public void PerformInitialSetup(IdentityEFContext context) 
    { 
     // initial configuration will go here 
    } 
    } 
} 

//实体配置是

我使用以下程序生成dev的数据库作为:

namespace DataAccess 
{ 
    public class BaseEfConfiguration<TEntity> : EntityTypeConfiguration<TEntity> 
    where TEntity : BaseEF 
    { 
    public BaseEfConfiguration() 
    { 
     Property(b => b.ServerVersion).IsOptional(); 
     ... 
    } 
    } 

    public class ActivityConfig : BaseEfConfiguration<Activity> 
    { 
    public ActivityConfig() 
     : base() 
    { 
     ToTable("Activities"); 
     Property(a => a.Name).IsRequired(); 
     HasRequired(a => a.CreatedBy).WithMany(u => u.ActivitiesCreated).WillCascadeOnDelete(false); 
     ... 
    } 
    } 
} 

// connectionstring in app.config 
<connectionStrings> 
    <add name="IdentityEFContext" 
     providerName="System.Data.SqlClient" 
     connectionString="Server=localhost; Integrated Security=False; Database=EFUpdateTest1_Azure; User Id=dbtest; Password=Hello.123" /> 
    </connectionStrings> 

User类是:

public class User : IdentityUser 
{ 
    public string Alias { get; set; } 
    ... 
} 

回答

0

使得模型更改后创建测试数据库之前我还没有加入迁移。我没有意识到,如果包含实体模型的项目启用了迁移,那么使用该模型创建数据库的项目将使用现有的迁移信息来创建数据库,而不是EntityTypeConfiguration信息。

解决方案是在更新模型后首先添加迁移。然后像往常一样尝试创建测试数据库。

希望这对某人有用。