2015-09-30 59 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

相关问题