Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体核心FluentAPI-作为主键和外键的ID_C#_Entity Framework_Entity Framework Core_Ef Fluent Api - Fatal编程技术网

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);
      }
      }
      }
      
    • 我的映射类

      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);
          }
      }
      
      公共类用户映射:EntityTypeConfigurationBase { 新的公共void配置(EntityTypeBuilder) { builder.HasKey(u=>u.Id); 建设者 .HasOne(u=>u.ProfileItem) .WithOne() .HasForeignKey(p=>p.Id) .IsRequired() .OnDelete(DeleteBehavior.Cascade); 建造商。可转让(“用户”); 配置(生成器); } }
    问题出在映射类的Configure方法中。在基类中,我需要忽略一些共享属性,在映射类中,我需要进行自定义映射。所使用的方法名为
    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);
      }
      }
      }
      
    • 我的映射类

      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);
          }
      }
      
      公共类用户映射:EntityTypeConfigurationBase { 新的公共void配置(EntityTypeBuilder) { builder.HasKey(u=>u.Id); 建设者 .HasOne(u=>u.ProfileItem) .WithOne() .HasForeignKey(p=>p.Id) .IsRequired() .OnDelete(DeleteBehavior.Cascade); 建造商。可转让(“用户”); 配置(生成器); } }
    问题出在映射类的Configure方法中。在基类中,我需要忽略一些共享属性,在映射类中,我需要进行自定义映射。所使用的方法名为
    Configure
    ,需要为映射实现该方法。由于基类和派生类都使用相同的方法名,因此会导致重复调用。第一个调用是基类型方法,第二个调用是映射类。映射完成了两次,并且在第一次映射时生成了外键(我的问题)


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

    除最后一次(双重映射)之外的所有尝试都是正确的,应该可以工作。只要确保使用
    .WithOn即可