Entity Framework Core 与备用路径的关系

问题描述 投票:0回答:1

我想使用 Entity Framework Core 8(仅)从我无法修改的数据库(首先是数据库)读取,并且该数据库不包含显式外键。因此,在搭建脚手架之后,我需要手动定义关系。我需要帮助定义两个表之间的关系,该关系可以直接通过外键,也可以通过第三个表间接(如果未定义外键)。

考虑以下实体

public partial class Procedure
{
    [key]
    public string ProcedureId { get; set; }

    public string ProcedureName { get; set; }

    // Foreign keys
    public string DocumentBaseId { get; set; }
    public string SpecificVersionId { get; set; }

    // Navigation properties
    public DocumentBase DocumentBase { get; set; }
    public DocumentVersion SpecificVersion { get; set; }
}

public class DocumentBase
{
    [key]
    public string DocumentBaseId { get; set; }

    public string DocumentName { get; set; }

    // Foreign key
    public string DefaultVersionId { get; set; }

    // Navigation properties
    public ICollection<DocumentVersion > DocumentVersions { get; set; } = new List<DocumentVersion >();
    public DocumentVersion DefaultVersion { get; set; }
}

public class DocumentVersion
{
    [key]
    public string DocumentVersionId { get; set; }

    public string VersionName { get; set; }

    // Foreign keys
    public string DocumentBaseId { get; set; }
    public string AuthorId { get; set; }

    // Navigation properties
    public DocumentBase DocumentBase { get; set; }
    public Author Author { get; set; }
}

public class Author
{
    [key]
    public string AuthorId { get; set; }

    public string AuthorName { get; set; }

    // Navigation property
    public ICollection<DocumentVersion > DocumentVersions { get; set; } = new List<DocumentVersion >();
}

以及以下上下文

            modelBuilder.Entity<Procedure>()
                .HasOne(p => p.DocumentBase)
                .WithOne()
                .HasForeignKey<Procedure>(p => p.DocumentBaseId)
                .IsRequired();

            modelBuilder.Entity<Procedure>()
                .HasOne(p => p.SpecificVersion)
                .WithOne()
                .HasForeignKey<Procedure>(p => p.SpecificVersionId);

            modelBuilder.Entity<DocumentBase>()
                .HasOne(db => db.DefaultVersion)
                .WithOne()
                .HasForeignKey<DocumentBase>(db => db.DefaultVersionId);

            modelBuilder.Entity<DocumentVersion>()
                .HasOne(dv => dv.DocumentBase)
                .WithMany(db => db.DocumentVersions)
                .HasForeignKey(dv => dv.DocumentBaseId)
                .IsRequired();

            modelBuilder.Entity<DocumentVersion>()
                .HasOne(dv => dv.Author)
                .WithMany(a => a.DocumentVersions)
                .HasForeignKey(dv => dv.AuthorId)
                .IsRequired();

如何定义关系

public partial class Procedure
{
    // Another navigation property
    public DocumentVersion CurrentVersion => SpecificVersion ?? DocumentBase.DefaultVersion;
}

这样查询就可以使用这种关系?例如

string author = context.Procedures.FirstOrDefault(p => p.ProcedureName == "p1").CurrentVersion.Author;

关系的等效 SQL 是

from Procedure p

join DocumentVersion dv join DocumentBase db on dv.DocumentBaseId == db.DocumentBaseId on ((p.SpecificVersionId = dv.DocumentVersionId) or (p.DocumentBaseId = db.DocumentBaseId and db.DefaultVersionId = dv.DocumentVersionId))

我尝试简单地添加只读属性,但它导致了 NullReferenceException。

我尝试了外键的复杂表达式

            modelBuilder.Entity<Procedure>()
                .HasOne(p => p.DocumentVersion)
                .WithOne()
                .HasForeignKey<Procedure>(p => p.SpecificVersionId ?? p.DocumentBase.DefaultVersionId);

但这不受支持。

entity-framework-core
1个回答
0
投票

Entity Framework Core 不支持非简单外键的关系。 EF Core 工具和扩展页面描述了可与 Entity Framework Core 一起使用的扩展。我选择了linq2db.EntityFrameworkCore

var query = from p in context.Procedure
    where p.ProcedureId == Identifier
    from db in context.DocumentBase
    from dv in context.DocumentVersion.Where(
        dv => dv.DocumentBaseId == db.DocumentBaseId &&
        (dv.DocumentVersionId == p.SpecificVersionId ||
        p.DocumentBaseId == db.DocumentBaseId && dv.DocumentVersionId == db.DefaultVersionId))
    select new
    {
        Version = dv.VersionName,
    };
© www.soinside.com 2019 - 2024. All rights reserved.