Entity Core FluentAPI - 作为主键和外键的 ID
Entity Core FluentAPI - An ID as Primary and Foreign Key
我有两个实体 User
和 Profile
。这些实体中的每一个都继承自包含 Id
属性 的 Entity
class。用户和配置文件之间的关系是一对一的关系。我正在尝试使用为用户实体创建的相同 Id 作为配置文件实体的 Id,即 User.Id == Profile.Id
.
我一直在尝试使用 FluentAPI 执行此操作,但我做不到。我已经阅读了这个 and also read this 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>
{
}
这是我迄今为止的试验,其中全部失败:
此映射在 User
table:
中生成了一个 ProfileItemId
modelBuilder.Entity<User>().HasOne(u => u.ProfileItem)
.WithOne()
.HasForeignKey<Profile>(p => p.Id)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
我尝试在 User
的 Profile
实体中添加反向导航 属性。 User
table 已正确映射,但 UserId
列已添加到 Profile
table:
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 一起工作?
@Ivan 说的对。在我发布的示例中,我在 OnModelCreating 事件上进行了映射,但在我的实际代码中,我使用了基数 class 进行映射,这就是问题所在。
这是我当前产生问题的代码:
实体映射的基础class
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);
}
}
}
我的映射class
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 方法中的映射 class 中。在基础 class 中,我需要忽略一些共享属性,而在映射 classes 中,我需要进行自定义映射。使用的方法名为 Configure
,映射需要实现该方法。由于相同的方法名称用于基础和派生 classes,这导致了重复调用。第一次调用是针对基本类型方法,第二次是针对映射 classes。映射了两次,外键(我的问题)是在第一次映射时生成的。
此问题的解决方案是将基类型方法标记为 virtual
,然后覆盖基类型上的方法。基本类型方法调用将采用相同的 ModelBuilder
对象,不会再次复制映射。
我有两个实体 User
和 Profile
。这些实体中的每一个都继承自包含 Id
属性 的 Entity
class。用户和配置文件之间的关系是一对一的关系。我正在尝试使用为用户实体创建的相同 Id 作为配置文件实体的 Id,即 User.Id == Profile.Id
.
我一直在尝试使用 FluentAPI 执行此操作,但我做不到。我已经阅读了这个
这是我的实体的代码:
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>
{
}
这是我迄今为止的试验,其中全部失败:
此映射在
中生成了一个User
table:ProfileItemId
modelBuilder.Entity<User>().HasOne(u => u.ProfileItem) .WithOne() .HasForeignKey<Profile>(p => p.Id) .IsRequired() .OnDelete(DeleteBehavior.Cascade);
我尝试在
User
的Profile
实体中添加反向导航 属性。User
table 已正确映射,但UserId
列已添加到Profile
table: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 一起工作?
@Ivan 说的对。在我发布的示例中,我在 OnModelCreating 事件上进行了映射,但在我的实际代码中,我使用了基数 class 进行映射,这就是问题所在。
这是我当前产生问题的代码:
实体映射的基础class
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); } } }
我的映射class
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 方法中的映射 class 中。在基础 class 中,我需要忽略一些共享属性,而在映射 classes 中,我需要进行自定义映射。使用的方法名为 Configure
,映射需要实现该方法。由于相同的方法名称用于基础和派生 classes,这导致了重复调用。第一次调用是针对基本类型方法,第二次是针对映射 classes。映射了两次,外键(我的问题)是在第一次映射时生成的。
此问题的解决方案是将基类型方法标记为 virtual
,然后覆盖基类型上的方法。基本类型方法调用将采用相同的 ModelBuilder
对象,不会再次复制映射。