TPT基类主键标识约定

时间:2014-11-21 18:58:04

标签: c# ef-code-first entity-framework-6

我首先使用代码和TPT继承。正在生成实体的基本类型表,其主键上没有标识。 (如果有用,我可以发布代码)。我的人员表有一个主键,但不是“是身份”。子类表按预期生成。

由于它没有为基本类型生成主键,因此我尝试将HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)添加到Map中,这会破坏模型,我收到错误消息:

  

在类型'Orion.Data.Entities.Person'上为属性'Id'指定了冲突的配置设置:DatabaseGeneratedOption = None与DatabaseGeneratedOption = Identity冲突。

我搜索了可能为该属性指定“DatabaseGeneratedOption.None”的任何地方,并且它不在我的代码中。我假设它是EF6中的配置约定。我已经尝试调试.net来找到它破坏的地方,没有成功。

所以问题是,什么约定可能导致我可以禁用?或者还有什么在这里发挥作用?

编辑: 基础映射:

public abstract partial class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; } 
}

public class PersonMap : EntityTypeConfiguration<Person>
{
    public PersonMap()
    {
        // Primary Key
        this.HasKey(t => t.Id);

        // Properties
        this.Property(t => t.FirstName)
            .IsRequired()
            .HasMaxLength(25);

        this.Property(t => t.LastName)
            .IsRequired()
            .HasMaxLength(25);

        this.ToTable("People");
        this.Property(t => t.Id).HasColumnName("Id");
        //this.Property(t=>t.Id).HasColumnName("Id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
        this.Property(t => t.FirstName).HasColumnName("FirstName");
        this.Property(t => t.LastName).HasColumnName("LastName");

        // Relationship
        this.HasOptional(x => x.User)
            .WithRequired(x => x.Person).WillCascadeOnDelete(false);

        this.HasMany(a => a.Addresses).WithOptional().WillCascadeOnDelete(true);
    }
}

继承类:

public partial class ClientRep : Person
{
    public ClientRep()
    {
        this.Jobs = new ObservableCollection<Job>();
    }
    public int ClientId { get; set; }
    public bool? IsPrimaryContact { get; set; }
    public string JobContactType { get; set; }
    public Client Client { get; set; }
    public ICollection<Job> Jobs { get; set; }
}
public class ClientRepMap : EntityTypeConfiguration<ClientRep>
{
    public ClientRepMap()
    {
        this.HasKey(t => t.Id);

        this.Property(t => t.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

        this.ToTable("People_ClientRep");
        this.Property(t => t.ClientId).HasColumnName("ClientId");
        this.Property(t => t.IsPrimaryContact).HasColumnName("IsPrimaryContact");
        this.Property(t => t.JobContactType).HasColumnName("JobContactType");
        this.Property(t => t.Id).HasColumnName("Id");

        this.HasMany(t => t.Jobs)
            .WithMany(t => t.ClientReps)
            .Map(m =>
                {
                    m.ToTable("JobClientRep");
                    m.MapLeftKey("ClientRep_Id");
                    m.MapRightKey("Job_Id");
                });

        this.HasRequired(t => t.Client)
            .WithMany(t => t.ClientReps)
            .HasForeignKey(d => d.ClientId).WillCascadeOnDelete(false);
    }
}

然后在我的DbContext中:

public partial class ProgramDbContext : DbContext, IProgramDbContext
{
    static OrionDbContext()
    {
        Database.SetInitializer(new OrionContextSeedInitializer());
    }
    public OrionDbContext()
        : base("ConnectionString")
    {
        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.ProxyCreationEnabled = false;
    }
    //No DbSet for Person
    public IDbSet<ClientRep> ClientRep { get; set; }
    public IDbSet<ContactPerson> ContactPerson { get; set; }
    public IDbSet<OtherPerson1> OtherPerson1{ get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //modelBuilder.Conventions.AddBefore<StoreGeneratedIdentityKeyConvention>(new InheritanceKeyConvention());
        //modelBuilder.Conventions.Remove<StoreGeneratedIdentityKeyConvention>();

        //abridged
        modelBuilder.Configurations.Add(new PersonMap());
        modelBuilder.Configurations.Add(new ClientRepMap());
        modelBuilder.Configurations.Add(new ContactPersonMap());
        modelBuilder.Configurations.Add(new OtherPerson1Map());

        //modelBuilder.Entity<Person>()
        //    .Property(a => a.Id)
        //    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }

它似乎与StoreGeneratedIdentityKeyConvention有关 - 似乎将身份分配给我的所有其他实体,但是这个实体没有得到它......我假设它与抽象类有关。我试图用以下方法覆盖该配置:

modelBuilder.Entity<Person>()
.Property(a => a.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

但它仍然存在冲突。

1 个答案:

答案 0 :(得分:3)

那是8个小时的荒谬冒险!

Backstory:我首先通过执行逆向工程现有数据库导入代码。

这使我的继承实体生成了一个主键,但没有生成它们的身份。我删除了Id属性的所有映射,因为在继承的实体上不存在,只有基础。 (现在这一切都变得更有意义了......谢谢,浪费了一天!)

我继承的课程&amp;映射现在看起来像这样:

public partial class ClientRep : Person
{
    public ClientRep()
    {
        this.Jobs = new ObservableCollection<Job>();
    }
    public int ClientId { get; set; }
    public bool? IsPrimaryContact { get; set; }
    public string JobContactType { get; set; }
    public Client Client { get; set; }
    public ICollection<Job> Jobs { get; set; }
}
public class ClientRepMap : EntityTypeConfiguration<ClientRep>
{
    public ClientRepMap()
    {
        this.ToTable("People_ClientRep");
        this.Property(t => t.ClientId).HasColumnName("ClientId");
        this.Property(t => t.IsPrimaryContact).HasColumnName("IsPrimaryContact");
        this.Property(t => t.JobContactType).HasColumnName("JobContactType");
        this.HasMany(t => t.Jobs)
            .WithMany(t => t.ClientReps)
            .Map(m =>
                {
                    m.ToTable("JobClientRep");
                    m.MapLeftKey("ClientRep_Id");
                    m.MapRightKey("Job_Id");
                });
        this.HasRequired(t => t.Client)
            .WithMany(t => t.ClientReps)
            .HasForeignKey(d => d.ClientId).WillCascadeOnDelete(false);
    }
}

一旦我从逆向工程师那里删除了这些残余物,一切都按照需要生成。