EntityFramework 核心:使用映射对同一类型的对象集合进行建模 table

EntityFramework Core: Model with collection of objects of the same type using mapping table

希望有人能够回答这个问题,因为我正在努力寻找一个合适的答案。我已经有一段时间没有研究 EF 了,尤其是核心变体。

基本给出以下tables:

CREATE TABLE [Documents] (
[Id] BIGINT NOT NULL IDENTITY(1,1),
[Name] NVARCHAR(255) NOT NULL,
CONSTRAINT [PK_Documents] PRIMARY KEY CLUSTERED ([Id] ASC))

CREATE TABLE [DocumentDependencies] (
[DocumentId] BIGINT NOT NULL,
[DependentOnDocumentId] BIGINT NOT NULL,
CONSTRAINT [PK_DocumentDependencies] PRIMARY KEY CLUSTERED ([DocumentId] ASC, [DependentOnDocumentId] ASC),
CONSTRAINT [FK_DocumentDependencies_Documents] FOREIGN KEY ([DocumentId]) REFERENCES [Documents]([Id]),
CONSTRAINT [FK_DocumentDependencies_DocumentDependencies] FOREIGN KEY ([DependentOnDocumentId]) REFERENCES [Documents]([Id]))

那么我有一个模型:

public class Document {
    public long Id { get; set; }
    public IEnumerable<Document> DependentDocuments { get; set; }
}

关系定义为,一个文档可以有 0 个或多个依赖文档,如映射 table 所定义。 但是,我无法找到一种在 EFCore 中映射它的方法,而不必为 DependentDocument 创建一个我不想做的新对象。

有人有什么想法吗?谢谢。 尝试搜索合适的答案,但找不到真正匹配的答案。也许我的架构是错误的,但征求其他意见也无妨。

[更新] 在根据下面的 Martinauts 答案进行一些挖掘和搞乱实现之后,我想到了这个:

public class DocumentEntityTypeConfiguration : IEntityTypeConfiguration<Document>
{
    public void Configure(EntityTypeBuilder<Document> builder)
    {
        builder.ToTable("Documents");
        builder.HasKey(e => e.Id); js));
        builder.HasMany(d => d.DependentDocuments)
            .WithMany(p => p.InverseDependentDocuments)
            .UsingEntity<Dictionary<string, object>>(
                "DependentDocument",
                r => r
                    .HasOne<Document>()
                    .WithMany()
                    .HasForeignKey("DocumentId")
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_DependentDocuments_MainDocument"),
                l => l
                    .HasOne<Document>()
                    .WithMany()
                    .HasForeignKey("DependentDocumentId")
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_DependentDocuments_DependentDocument"),
                j =>
                {
                    j.HasKey("DocumentId", "DependentDocumentId");
                    j.ToTable("DependentDocuments");
                });
        builder.HasMany(d => d.InverseDependentDocuments)
            .WithMany(p => p.DependentDocuments)
            .UsingEntity<Dictionary<string, object>>(
                "DependentDocument",
                r => r
                    .HasOne<Document>()
                    .WithMany()
                    .HasForeignKey("DependentDocumentId")
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_DependentDocuments_DependentDocument"),
                l => l
                    .HasOne<Document>()
                    .WithMany()
                    .HasForeignKey("DocumentId")
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_DependentDocuments_MainDocument"),
                j =>
                {
                    j.HasKey("DocumentId", "DependentDocumentId");
                    j.ToTable("DependentDocuments");
                });
    }
}

不幸的是,仅使用上述配置是行不通的。 但是,如果我随后添加 NuGet 包 Microsoft.EntityFrameworkCore.Proxies 并启用 LazyLoading,它确实会检索依赖文档,但仅限于反向集合。任何人都知道为什么没有延迟加载它就不能工作?我已经尝试枚举列表以获取相关文档,但如果没有在上下文中启用 LazyLoading 功能,它似乎无法工作。

[更新#2] 实际上让它工作了,所以代码按照建议的答案工作,但需要记住也包括数据集:/

InverseDependentDocuments 属性 添加到 Document-class。

public class Document {
    public long Id { get; set; }
    public IEnumerable<Document> DependentDocuments { get; set; } 
    public IEnumerable<Document> InverseDependentDocuments { get; set; } 
}

您可以在 DbContext class 的 OnModelCreating 方法中使用模型构建器配置关系:

modelBuilder.Entity<Document>
    .HasMany(x => x.DependentDocuments)
    .WithMany(x => x.InverseDependentDocuments)
    .usingEntity(x => {
       x.ToTable("DocumentDependencies")
       // ... additional configuration for column naming
    });

这在documentation中也有解释。