[英]Configuring EF Core one to many mapping of different properties correctly
I'm using AutoMapper to map classes from Camille to my own domain classes, which I plan on storing using EF Core in my .NET 5 REST API. 一个特别讨厌的 class 给我带来了很多麻烦。 ParticipantTimeline class 包含几个带有统计信息的字典,如下所示:
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
}
到目前为止,我正在映射到我的域类,如下所示:
CamilleProfile.cs:
// Omitted for brevity
CreateMap<ParticipantTimeline, ParticipantTimelineDto>();
CreateMap<KeyValuePair<string, double>, ParticipantTimelineDelta>()
.ForMember(x => x.Delta, conf => conf.MapFrom(kvp => kvp.Key))
.ForMember(x => x.Value, conf => conf.MapFrom(kvp => kvp.Value));
参与者时间线Dto.cs:
public class ParticipantTimelineDto
{
public int ParticipantId { get; set; }
public IEnumerable<ParticipantTimelineDelta> CsDiffPerMinDeltas { get; set; }
public IEnumerable<ParticipantTimelineDelta> DamageTakenPerMinDeltas { get; set; }
public string Role { get; set; }
public IEnumerable<ParticipantTimelineDelta> DamageTakenDiffPerMinDeltas { get; set; }
public IEnumerable<ParticipantTimelineDelta> XpPerMinDeltas { get; set; }
public IEnumerable<ParticipantTimelineDelta> XpDiffPerMinDeltas { get; set; }
public string Lane { get; set; }
public IEnumerable<ParticipantTimelineDelta> CreepsPerMinDeltas { get; set; }
public IEnumerable<ParticipantTimelineDelta> GoldPerMinDeltas { get; set; }
}
参与者时间线Delta.cs:
public class ParticipantTimelineDelta
{
public string Delta { get; set; }
public double Value { get; set; }
public ParticipantTimelineDelta()
{
}
}
这在没有 EF 的情况下工作正常,但现在我正在尝试为身份添加迁移,但我无法弄清楚我与 EF 的映射。 尝试创建迁移时,我收到以下消息:
在没有配置外键属性的情况下,“ParticipantTimelineDelta”和“ParticipantTimelineDto”之间存在多种关系。 这将导致实体框架在“ParticipantTimelineDelta”上创建影子属性,其名称取决于发现顺序。
这只是一个警告,我理解它为什么这么说。 这是让我最困惑的实际错误。 如下:
实体类型“ParticipantTimelineDelta”需要定义一个主键。 如果您打算使用无密钥实体类型,请在“OnModelCreating”中调用“HasNoKey”。 有关无密钥实体类型的详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2141943。
这让我很困惑,因为我确实定义了一个 PK。 我不是特别喜欢我映射增量的方式,但是我还没有找到更好的方法来 devise。 无论如何,我想知道以我当前的配置是否有可能完全正确地对它们进行 map。 如果没有,我应该如何 map 否则三角洲?
这是我对 ParticipantTimeline 和 ParticipantTimelineDelta 的 EF 配置:
参与者时间线配置.cs:
public class ParticipantTimelineConfiguration : IEntityTypeConfiguration<ParticipantTimelineDto>
{
public void Configure(EntityTypeBuilder<ParticipantTimelineDto> builder)
{
builder.ToTable("ParticipantTimeline");
builder.HasKey(ps => ps.ParticipantId);
builder.HasMany<ParticipantTimelineDelta>()
.WithOne();
}
}
参与者时间线DeltaConfiguration.cs:
public class ParticipantTimelineDeltaConfiguration : IEntityTypeConfiguration<ParticipantTimelineDelta>
{
public void Configure(EntityTypeBuilder<ParticipantTimelineDelta> builder)
{
builder.ToTable("ParticipantTimelineDeltas");
builder.HasKey(d => d.Delta);
}
}
我尝试在 HasMany().WithOne() 语句上定义 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");
});
}
}
这不是特别漂亮的imo,我希望有更好的方法来做到这一点。 但是,这暂时可以。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.