C# 正确配置不同属性的EF Core一对多映射

C# 正确配置不同属性的EF Core一对多映射,c#,asp.net-web-api,entity-framework-core,C#,Asp.net Web Api,Entity Framework Core,我正在使用AutoMapper将类从映射到我自己的域类,我计划在.NET5RESTAPI中使用EFCore存储这些域类。然而,一门特别讨厌的课给我带来了一大堆麻烦。ParticipantTimeline类包含几个带有统计信息的字典,如下所示: namespace MingweiSamuel.Camille.MatchV4 { public class ParticipantTimeline { [JsonPropertyName("participantId"

我正在使用AutoMapper将类从映射到我自己的域类,我计划在.NET5RESTAPI中使用EFCore存储这些域类。然而,一门特别讨厌的课给我带来了一大堆麻烦。ParticipantTimeline类包含几个带有统计信息的字典,如下所示:

namespace MingweiSamuel.Camille.MatchV4
{
  public class ParticipantTimeline
  {
    [JsonPropertyName("participantId")]
    public int ParticipantId { get; set; }

    [JsonPropertyName("csDiffPerMinDeltas")]
    public IDictionary<string, double> CsDiffPerMinDeltas { get; set; }

    [JsonPropertyName("damageTakenPerMinDeltas")]
    public IDictionary<string, double> DamageTakenPerMinDeltas { get; set; }

    [JsonPropertyName("role")]
    public string Role { get; set; }

    [JsonPropertyName("damageTakenDiffPerMinDeltas")]
    public IDictionary<string, double> DamageTakenDiffPerMinDeltas { get; set; }

    [JsonPropertyName("xpPerMinDeltas")]
    public IDictionary<string, double> XpPerMinDeltas { get; set; }

    [JsonPropertyName("xpDiffPerMinDeltas")]
    public IDictionary<string, double> XpDiffPerMinDeltas { get; set; }

    [JsonPropertyName("lane")]
    public string Lane { get; set; }

    [JsonPropertyName("creepsPerMinDeltas")]
    public IDictionary<string, double> CreepsPerMinDeltas { get; set; }

    [JsonPropertyName("goldPerMinDeltas")]
    public IDictionary<string, double> GoldPerMinDeltas { get; set; }

    [JsonExtensionData]
    public Dictionary<string, object> _AdditionalProperties { get; set; } = new Dictionary<string, object>();

    //Methods omitted for brevity
  }
这在没有EF的情况下可以很好地工作,但现在我正在尝试添加身份的迁移,而我无法找出我与EF的映射。尝试创建迁移时,我收到以下消息:

在没有配置外键属性的情况下,“ParticipantTimelineDelta”和“ParticipantTimelineDto”之间存在多个关系。这将导致实体框架在“ParticipantTimelineDelta”上创建阴影属性,其名称取决于发现顺序

这只是一个警告,我理解它为什么这么说。这是最让我困惑的实际错误。详情如下:

实体类型“ParticipantTimelineDelta”需要定义主键。如果要使用无键实体类型,请在“OnModelCreating”中调用“HasNoKey”。有关无键实体类型的详细信息,请参见

这让我很困惑,因为我确实定义了PK。我并不特别喜欢绘制三角洲的方式,但我还没有想出更好的方法。不管怎么说,我想知道我目前的配置是否能够正确地映射它们。如果没有,我应该如何映射三角洲呢

以下是ParticipantTimeline和ParticipantTimelineDelta的EF配置:

参与者TimeLineConfiguration.cs:

public class ParticipantTimelineConfiguration : IEntityTypeConfiguration<ParticipantTimelineDto>
{
    public void Configure(EntityTypeBuilder<ParticipantTimelineDto> builder)
    {
        builder.ToTable("ParticipantTimeline");
        builder.HasKey(ps => ps.ParticipantId);
        builder.HasMany<ParticipantTimelineDelta>()
            .WithOne();
    }
}
public class ParticipantTimelineDeltaConfiguration : IEntityTypeConfiguration<ParticipantTimelineDelta>
{
    public void Configure(EntityTypeBuilder<ParticipantTimelineDelta> builder)
    {
        builder.ToTable("ParticipantTimelineDeltas");
        builder.HasKey(d => d.Delta);
    }
}
公共类参与者TimeLineConfiguration:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder)
{
建造商可转让表格(“参与人时间表”);
builder.HasKey(ps=>ps.ParticipantId);
builder.HasMany()
.WithOne();
}
}
参与者TimeLineDeltaConfiguration.cs:

public class ParticipantTimelineConfiguration : IEntityTypeConfiguration<ParticipantTimelineDto>
{
    public void Configure(EntityTypeBuilder<ParticipantTimelineDto> builder)
    {
        builder.ToTable("ParticipantTimeline");
        builder.HasKey(ps => ps.ParticipantId);
        builder.HasMany<ParticipantTimelineDelta>()
            .WithOne();
    }
}
public class ParticipantTimelineDeltaConfiguration : IEntityTypeConfiguration<ParticipantTimelineDelta>
{
    public void Configure(EntityTypeBuilder<ParticipantTimelineDelta> builder)
    {
        builder.ToTable("ParticipantTimelineDeltas");
        builder.HasKey(d => d.Delta);
    }
}
公共类参与者TimeLineDeltaConfiguration:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder)
{
可转让建筑商(“参与者时间线三角”);
builder.HasKey(d=>d.Delta);
}
}

我尝试在HasMany()语句中定义HasForeignKey,但没有成功。

Ivan Stoev的评论最终为我指明了正确的方向。我对ParticipantTimelineConfiguration进行了以下更改:

public class ParticipantTimelineConfiguration : IEntityTypeConfiguration<ParticipantTimelineDto>
{
    public void Configure(EntityTypeBuilder<ParticipantTimelineDto> builder)
    {
        builder.ToTable("ParticipantTimeline");
        builder.HasKey(ps => ps.ParticipantId);
        builder.OwnsMany(pt => pt.CreepsPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.CsDiffPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.DamageTakenDiffPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.DamageTakenPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.GoldPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.XpDiffPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.XpPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
    }
}
公共类参与者TimeLineConfiguration:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder)
{
建造商可转让表格(“参与人时间表”);
builder.HasKey(ps=>ps.ParticipantId);
builder.OwnsMany(pt=>pt.indeltas,a=>
{
a、 WithOwner().HasForeignKey(“参与者TimeLineId”);
a、 财产(“Id”);
a、 HasKey(“Id”);
});
builder.OwnsMany(pt=>pt.CsDiffPerMinDeltas,a=>
{
a、 WithOwner().HasForeignKey(“参与者TimeLineId”);
a、 财产(“Id”);
a、 HasKey(“Id”);
});
builder.OwnsMany(pt=>pt.DamageTakenDiffPerMinDeltas,a=>
{
a、 WithOwner().HasForeignKey(“参与者TimeLineId”);
a、 财产(“Id”);
a、 HasKey(“Id”);
});
builder.OwnsMany(pt=>pt.DamageTakenPerMinDeltas,a=>
{
a、 WithOwner().HasForeignKey(“参与者TimeLineId”);
a、 财产(“Id”);
a、 HasKey(“Id”);
});
builder.OwnsMany(pt=>pt.GoldPerMinDeltas,a=>
{
a、 WithOwner().HasForeignKey(“参与者TimeLineId”);
a、 财产(“Id”);
a、 HasKey(“Id”);
});
builder.OwnsMany(pt=>pt.XpDiffPerMinDeltas,a=>
{
a、 WithOwner().HasForeignKey(“参与者TimeLineId”);
a、 财产(“Id”);
a、 HasKey(“Id”);
});
builder.OwnsMany(pt=>pt.XpPerMinDeltas,a=>
{
a、 WithOwner().HasForeignKey(“参与者TimeLineId”);
a、 财产(“Id”);
a、 HasKey(“Id”);
});
}
}

在我看来,这并不特别漂亮,我希望有更好的方法来做到这一点。不过,现在就这样。

这个问题与AutoMapper无关,因此您可以删除该部分(和标签),因为它只会污染帖子。至于如何将其映射到数据库,您必须了解关系数据库如何存储一对多关系。它们不嵌入“父项”,而是存储在单独的表中,并与一个称为外键的特殊键列相关。因此,每个集合属性都应该映射到一个单独的表。例如,我认为映射中的另一种方法可以简化在EF中映射类的过程,因此我将其保留在那里。我现在已经取下了标签。
public class ParticipantTimelineConfiguration : IEntityTypeConfiguration<ParticipantTimelineDto>
{
    public void Configure(EntityTypeBuilder<ParticipantTimelineDto> builder)
    {
        builder.ToTable("ParticipantTimeline");
        builder.HasKey(ps => ps.ParticipantId);
        builder.OwnsMany(pt => pt.CreepsPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.CsDiffPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.DamageTakenDiffPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.DamageTakenPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.GoldPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.XpDiffPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
        builder.OwnsMany(pt => pt.XpPerMinDeltas, a =>
        {
            a.WithOwner().HasForeignKey("ParticipantTimelineId");
            a.Property<int>("Id");
            a.HasKey("Id");
        });
    }
}