2015-09-30 60 views
0

我一直在經歷着的ObjectContext不一致的狀態異常:實體框架TPC:爲什麼BaseEntity ID需要是Guid類型?

到數據庫的更改已成功提交,但在更新對象上下文時發生錯誤 。 ObjectContext可能是 處於不一致狀態。內部異常消息:AcceptChanges 無法繼續,因爲對象的鍵值與ObjectStateManager中的另一個 對象衝突。在調用AcceptChanges之前,確保鍵值爲 唯一。

這似乎發生時,我的基實體(因爲使用TPC抽象)具有

public int Id { get; set;} 

,其被配置爲通過所述數據庫生成的主密鑰:

// Base Entity 
modelBuilder.Entity<BaseEntityObject>().HasKey(t => t.Id); 
modelBuilder.Entity<BaseEntityObject>().Property(t => t.Id). 
    HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

和衍生實體也繼承這一點並試圖將其用作主鍵。

當您實例化兩種不同類型的派生條目時,將它們添加到DbContext中,然後嘗試SaveChanges(),異常被觸發。但是,當Id字段從int更改爲Guid時:

public Guid Id { get; set;} 

此異常不再被拋出。

  1. 有人可以解釋爲什麼發生這種情況時,Id屬性的類型爲int?

  2. 有沒有解決方法呢?讓每個派生實體都擁有Guid PK似乎有點浪費。

+0

您可以發佈你的基地和子類的一個例子嗎?另外,您的ID列是否在編輯器中標記爲IsIdentity? – Robert

+0

我絕對可以發佈一個基礎和一個孩子類的例子。你的意思是「你的ID列,在編輯器中標記爲IsIdentity」? – blgrnboy

+0

您的'ID'列是否標記爲'PrimaryKey'並且設置爲數據庫中的'Identity'列,如果是,它是否在EDMX模型編輯器中將EntityKey屬性設置爲'true'? – Robert

回答

1

我認爲你面臨的問題是因爲你配置基礎機構的主鍵和身份,但你應該因爲一般來說,我們不是在數據庫中存儲BaseEntityObject做同樣爲您的派生實體。

你需要做類似如下:

modelBuilder.Entity<DerivedEntityObject1>().HasKey(t => t.Id); 
modelBuilder.Entity<DerivedEntityObject1>().Property(t => t.Id). 
    HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

modelBuilder.Entity<DerivedEntityObject2>().HasKey(t => t.Id); 
modelBuilder.Entity<DerivedEntityObject2>().Property(t => t.Id). 
    HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

更新:

  1. 創建基礎實體類型配置和繼承,在你的實體配置。

    public class TestContext : DbContext 
    { 
        public DbSet<TestEntity1> TestEntities1 { get; set; } 
        public DbSet<TestEntity2> TestEntities2 { get; set; } 
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder) 
        { 
         modelBuilder.Configurations.Add(new TestEntity1Configuration()); 
         modelBuilder.Configurations.Add(new TestEntity2Configuration()); 
    
         base.OnModelCreating(modelBuilder); 
        } 
    } 
    
    public class BaseEntityConfiguration<T> : EntityTypeConfiguration<T> where T : BaseEntity 
    { 
        public BaseEntityConfiguration() 
        { 
         HasKey(d => d.Id).Property(d => d.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity); 
        } 
    } 
    
    public class TestEntity1Configuration : BaseEntityConfiguration<TestEntity1> { 
        //your configuration here. 
    } 
    
    public class TestEntity2Configuration : BaseEntityConfiguration<TestEntity2> { 
        //your configuration here. 
    } 
    
  2. 聰明的方法是使用數據標註如下圖所示:

    public class BaseEntity 
    { 
        [Key] 
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)] 
        public int Id { get; set; } 
    } 
    
    public class TestEntity1 : BaseEntity 
    { 
        public string Name { get; set; } 
    } 
    
    public class TestEntity2 : BaseEntity 
    { 
        public string Name2 { get; set; } 
    } 
    
+0

在這種情況下,我是否需要消除主鍵的modelBuilder.Entity 配置? – blgrnboy

+0

@blgrnboy是當你沒有將它保存在數據庫中時,爲什麼你需要爲它配置EF模型! –

+0

因爲基礎實體中所有類都有其他常見屬性。 – blgrnboy

相關問題