2017-10-14 145 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信息。

解決方案是在更新模型後首先添加遷移。然後像往常一樣嘗試創建測試數據庫。

希望這對某人有用。