实体核心FluentAPI - 作为主键和外键的ID

时间:2017-11-20 08:28:46

标签: c# entity-framework entity-framework-core ef-fluent-api

我有两个实体UserProfile。每个实体都继承自Entity类,其中包含Id属性。用户和个人资料之间的关系是一对一的关系。我正在尝试使用为User实体创建的相同Id作为Profile实体的Id,即User.Id == Profile.Id

我一直试图用FluentAPI做到这一点,但我无法做到。我已阅读此question并阅读此post,但我仍然无法找到解决问题的方法。

以下是我的实体的代码:

public class Entity<TKey> : IEntity
{
    /// <summary>
    /// Unique identifier for this entity.
    /// </summary>
    public virtual int Id { get; set; }
}

public class User : Entity<int>
{
    public virtual Profile ProfileItem { get; set; }
}

public class Profile : Entity<int> 
{

}

到目前为止,我的审判都失败了:

  • 此映射在ProfileItemId表中生成User

    modelBuilder.Entity<User>().HasOne(u => u.ProfileItem)
        .WithOne()
        .HasForeignKey<Profile>(p => p.Id)
        .IsRequired()
        .OnDelete(DeleteBehavior.Cascade);
    
  • 我尝试在Profile实体中为User添加反向导航属性。 User表已正确映射,但UserId表中添加了Profile列:

    modeBuilder.Entity<User>().HasOne(u => u.ProfileItem)
        .WithOne(u => u.User)
        .HasForeignKey<Profile>(p => p.Id)
        .IsRequired()
        .OnDelete(DeleteBehavior.Cascade);
    

我之前提到的问题中报告的唯一解决此问题的方法是,您必须添加反向属性,然后使用数据注释。我尝试了以下内容并且有效:

public class Entity<TKey> : IEntity
{
    /// <summary>
    /// Unique identifier for this entity.
    /// </summary>
    public virtual int Id { get; set; }
}

public class User : Entity<int>
{
    [InverseProperty("User")]
    public virtual Profile ProfileItem { get; set; }
}

public class Profile : Entity<int> 
{
    [ForeignKey("Id")]
    public virtual User User { get; set; }
}

如何使用FluentAPI?

1 个答案:

答案 0 :(得分:0)

@Ivan说的是对的。在我发布的示例中,我在OnModelCreating事件上进行了映射,但在我的实际代码中,我使用了基类进行映射,这就是问题所在。

这是我当前产生问题的代码:

  • 实体映射的基类

    public class EntityTypeConfigurationBase<T> : IEntityTypeConfiguration<T> where T : class, IEntity
    {
        private bool BIgnoreBaseProps = true;
    
        public EntityTypeConfigurationBase(bool bIgnoreBaseProps = true) : base()
        {
            BIgnoreBaseProps = bIgnoreBaseProps;
        }
    
        public void Configure(EntityTypeBuilder<T> builder)
        {
            if (BIgnoreBaseProps)
            {
                builder.Ignore(x => x.State);
                builder.Ignore(x => x.AssociationState);
            }
        }
    }
    
  • 我的映射类

    public class UserMap : EntityTypeConfigurationBase<User>
    {
    
       new public void Configure(EntityTypeBuilder<User> builder)
       {
    
        builder.HasKey(u => u.Id);
        builder
            .HasOne(u => u.ProfileItem)
            .WithOne()
            .HasForeignKey<Profile>(p => p.Id)
            .IsRequired()
            .OnDelete(DeleteBehavior.Cascade);
        builder.ToTable("User");
    
        base.Configure(builder);
        }
    }
    

问题出在映射类的Configure方法中。在基类中,我需要忽略一些共享属性,在映射类中,我需要进行自定义映射。使用的方法名为Configure,需要为映射实现。由于同一方法名称用于基类和派生类,因此导致重复调用。第一个调用是基类型方法,第二个调用是映射类。映射完成了两次,并在第一个映射上生成了外键(我的问题)。

此问题的解决方案是将基类型方法标记为virtual,然后覆盖基类型上的方法。基类型方法调用将采用相同的ModelBuilder对象,并且不会再次复制映射。