C# 实体核心FluentAPI-作为主键和外键的ID
我有两个实体C# 实体核心FluentAPI-作为主键和外键的ID,c#,entity-framework,entity-framework-core,ef-fluent-api,C#,Entity Framework,Entity Framework Core,Ef Fluent Api,我有两个实体User和Profile。这些实体中的每一个都继承自包含Id属性的实体类。用户和配置文件之间的关系是一对一的关系。我试图使用为用户实体创建的相同Id作为概要文件实体的Id,即User.Id==Profile.Id 我一直试图用FluentAPI来做这件事,但我做不到。我读过这篇文章,也读过这篇文章,但我仍然找不到解决问题的办法 以下是我的实体的代码: public class Entity<TKey> : IEntity { /// <summary>
User
和Profile
。这些实体中的每一个都继承自包含Id
属性的实体
类。用户和配置文件之间的关系是一对一的关系。我试图使用为用户实体创建的相同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
的Profile
实体中添加反向导航属性。User
表已正确映射,但UserId
列已添加到Profile
表中:
modelBuilder.Entity<User>().HasOne(u => u.ProfileItem)
.WithOne()
.HasForeignKey<Profile>(p => p.Id)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
modeBuilder.Entity<User>().HasOne(u => u.ProfileItem)
.WithOne(u => u.User)
.HasForeignKey<Profile>(p => p.Id)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
modeBuilder.Entity().HasOne(u=>u.ProfileItem)
.WithOne(u=>u.User)
.HasForeignKey(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; }
}
公共类实体:IEntity
{
///
///此实体的唯一标识符。
///
公共虚拟整数Id{get;set;}
}
公共类用户:实体
{
[反向属性(“用户”)]
公共虚拟配置文件配置文件项{get;set;}
}
公共类配置文件:实体
{
[外国钥匙(“Id”)]
公共虚拟用户用户{get;set;}
}
如何在使用FluentAPI时获得同样的效果?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); } } }
公共类EntityTypeConfigurationBase:IEntityTypeConfiguration其中T:class,IEntity { private bool BIgnoreBaseProps=true; public EntityTypeConfigurationBase(bool-bIgnoreBaseProps=true):base() { BIgnoreBaseProps=BIgnoreBaseProps; } 公共void配置(EntityTypeBuilder) { if(BIgnoreBaseProps) { 忽略(x=>x.State); 忽略(x=>x.AssociationState); } } }
- 我的映射类
公共类用户映射:EntityTypeConfigurationBase { 新的公共void配置(EntityTypeBuilder) { builder.HasKey(u=>u.Id); 建设者 .HasOne(u=>u.ProfileItem) .WithOne() .HasForeignKey(p=>p.Id) .IsRequired() .OnDelete(DeleteBehavior.Cascade); 建造商。可转让(“用户”); 配置(生成器); } }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
,需要为映射实现该方法。由于基类和派生类都使用相同的方法名,因此会导致重复调用。第一个调用是基类型方法,第二个调用是映射类。映射完成了两次,并且在第一次映射时生成了外键(我的问题)
此问题的解决方案是将基类型方法标记为
virtual
,然后在基类型上重写该方法。基本类型方法调用将采用相同的ModelBuilder
对象,并且不会再次复制映射。@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); } } }
公共类EntityTypeConfigurationBase:IEntityTypeConfiguration其中T:class,IEntity { private bool BIgnoreBaseProps=true; public EntityTypeConfigurationBase(bool-bIgnoreBaseProps=true):base() { BIgnoreBaseProps=BIgnoreBaseProps; } 公共void配置(EntityTypeBuilder) { if(BIgnoreBaseProps) { 忽略(x=>x.State); 忽略(x=>x.AssociationState); } } }
- 我的映射类
公共类用户映射:EntityTypeConfigurationBase { 新的公共void配置(EntityTypeBuilder) { builder.HasKey(u=>u.Id); 建设者 .HasOne(u=>u.ProfileItem) .WithOne() .HasForeignKey(p=>p.Id) .IsRequired() .OnDelete(DeleteBehavior.Cascade); 建造商。可转让(“用户”); 配置(生成器); } }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
,需要为映射实现该方法。由于基类和派生类都使用相同的方法名,因此会导致重复调用。第一个调用是基类型方法,第二个调用是映射类。映射完成了两次,并且在第一次映射时生成了外键(我的问题)
此问题的解决方案是将基类型方法标记为
virtual
,然后在基类型上重写该方法。基本类型方法调用将采用相同的ModelBuilder
对象,并且不会再次复制映射。除最后一次(双重映射)之外的所有尝试都是正确的,应该可以工作。只要确保使用.WithOn即可