c# - EFCore - 如何将多个导航属性设置为同一类型?
问题描述
我的模型包含 Post 和 PostHistory 类,其中 Post 与 PostHistory 是一对多的关系。
class Post
{
public int Id { get; set; }
public PostVersion CurrentVersion { get; set; }
public PostVersion OriginalVersion { get; set; }
public IList<PostVersion> History { get; set; }
}
class PostVersion
{
public int Id { get; set; }
public Post Post { get; set; }
public string Title { get; set; }
public string Body { get; set; }
}
History 属性包含与该 Post 相关的所有 PostVersions 的列表。CurrentVersion 和 PreviousVersion 属性都引用了该帖子历史记录中的特定版本(最有可能是最新版本和第一个版本)。
我的问题是,由于 CurrentVersion 和 OriginalVersion 导航属性,EF Core 难以理解这种关系。当我尝试创建迁移时,我收到以下错误消息:
Unable to determine the relationship represented by navigation property 'Post.CurrentVersion' of type 'PostVersion'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
之后,我尝试使用 Fluent API 手动创建关系。
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Post>()
.HasMany(x => x.History)
.WithOne(x => x.Post);
builder.Entity<Post>()
.HasOne(x => x.CurrentVersion)
.WithOne(x => x.Post);
builder.Entity<Post>()
.HasOne(x => x.OriginalVersion)
.WithOne(x => x.Post);
}
但产生了一个不同的错误:
Cannot create a relationship between 'PostVersion.Post' and 'Post.CurrentVersion', because there already is a relationship between 'Post.History' and 'PostVersion.Post'. Navigation properties can only participate in a single relationship.
是否可以在 EF Core 代码优先中创建这种关系?
解决方案
编辑 我做了一些更改,您不能在多个关系中引用相同的属性。因此我不得不使用外键进行映射。PostVersion只有一个您需要的Post参考。
public class Post
{
public Guid Id { get; set; }
public Guid CurrentVersionId { get; set; }
public PostVersion CurrentVersion { get; set; }
public Guid OriginalVersionId { get; set; }
public PostVersion OriginalVersion { get; set; }
public IList<PostVersion> History { get; set; }
}
public class PostVersion
{
public Guid Id { get; set; }
public Guid PostId { get; set; }
public Post Post { get; set; }
public string Title { get; set; }
public string Body { get; set; }
}
modelBuilder.Entity<Post>()
.HasOne(x => x.CurrentVersion)
.WithOne()
.HasForeignKey<Post>(p => p.CurrentVersionId);
modelBuilder.Entity<Post>()
.HasOne(x => x.OriginalVersion)
.WithOne()
.HasForeignKey<Post>(p => p.OriginalVersionId);
modelBuilder.Entity<Post>()
.HasMany(x => x.History)
.WithOne(p => p.Post)
.HasForeignKey(pv => pv.PostId);
原始 您需要为第二个关系指定附加属性
public class Post
{
public Guid Id { get; set; }
public PostVersion CurrentVersion { get; set; }
public PostVersion OriginalVersion { get; set; }
public IList<PostVersion> History { get; set; }
}
public class PostVersion
{
public Guid Id { get; set; }
public Post Post { get; set; }
public Post SecondPost { get; set; }
public Post ThirdPost { get; set; }
public string Title { get; set; }
public string Body { get; set; }
}
modelBuilder.Entity<Post>()
.HasOne(x => x.CurrentVersion)
.WithOne(x => x.Post);
modelBuilder.Entity<Post>()
.HasOne(x => x.OriginalVersion)
.WithOne(x => x.SecondPost);
modelBuilder.Entity<Post>()
.HasMany(x => x.History)
.WithOne(x => x.ThirdPost);
推荐阅读
- java - Why does this error occur? An established connection was aborted by the software in your host machine
- java - Swing context menu on JavaFX Chart
- php - Laravel Validation - Array fields, only one of two allowed but neither is required
- mysql - ErrorException (E_ERROR) 未定义变量:buildingSections
- r - 按组匹配行值(r,data.table)
- android - 安装 Ad-Hoc Android 应用程序
- angular - 启动时淡入动画
- javascript - How can I refresh a page every 5 minutes starting at 8:01 a.m. and then 8:06 a.m. and so on.
- asp.net - web api attribute routing multiple parameters
- angular - Angular 6 和 aws-amplify 通用网络错误