如何查询带有子 table 集合的视图?

How to query a view with child table collection?

我想在 EF Core 3.1 中查询带有子 table 集合的视图。 以我的简化示例为例,其中包含 3 tables:

public class Relation
{
    public long Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Invoice
{
    public long Id { get; set; }
    public string Reference { get; set; }

    public long RelationId { get; set; }
    public virtual Relation Relation { get; set; }

    public virtual ICollection<InvoiceLine> InvoiceLines { get; set; } = new HashSet<InvoiceLine>();
}

public class InvoiceLine
{
    public long Id { get; set; }
    public decimal Amount { get; set; }
    public decimal Price { get; set; }
    public string ArticleReference { get; set; }

    public long InvoiceId { get; set; }
    public virtual Invoice Invoice { get; set; }
}

我将 SQL 视图添加到我的迁移中:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.Sql(@"
        CREATE OR ALTER VIEW dbo.InvoiceOverview
        AS
        SELECT 
            i.Id
            ,i.Reference
            ,r.FistName + ' ' + r.LastName as Name
        FROM dbo.Invoices i
        INNER JOIN Relations r ON r.Id = i.RelationId");
}

InvoiceView 模型 + 配置

public class InvoiceView
{
    public long Id { get; set; }
    public string Reference { get; set; }
    public string Name { get; set; }
}

public void Configure(EntityTypeBuilder<InvoiceOverview> builder)
{
    builder.HasKey(_ => _.Id);
    builder.ToView("InvoiceOverview");
}

到目前为止一切顺利。以上所有工作,但我希望能够像这样查询发票行:

Context.InvoiceOverview.AsNoTracking().AsQueryable().Where(_ =>
    _.InvoiceLines.Select(invoiceLine => invoiceLine.ArticleReference)
        .Any(articleReference => articleReference == "Test").ToListAsync();

我将 InvoiceLine-collection 添加到 InvoiceOverview 模型并更新了配置。

public class InvoiceView
{
    public long Id { get; set; }
    public string Reference { get; set; }
    public string Name { get; set; }

    public virtual ICollection<InvoiceLine> InvoiceLines { get; set; }
}

public void Configure(EntityTypeBuilder<InvoiceOverview> builder)
{
    builder.HasKey(_ => _.Id);
    builder.ToView("InvoiceOverview");

    builder.HasMany(_ => _.InvoiceLines)
        .WithOne()
        .HasForeignKey(_ => _.InvoiceId);
}

通过上面的配置,我可以运行查询成功了。 我现在唯一的问题是,当我 运行 'Add-Migration' 时,他们想要创建一个外键。无法为视图创建外键(并且外键已经存在于视图中使用的 table 上)。

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.AddForeignKey(
        name: "FK_InvoiceLines_InvoiceOverview_InvoiceId",
        table: "InvoiceLines",
        column: "InvoiceId",
        principalTable: "InvoiceOverview",
        principalColumn: "Id",
        onDelete: ReferentialAction.Cascade);
}

是否可以在生成迁移脚本时显式忽略外键,还是我应该以不同的方式编写配置?

我在

中找到了解决方案
public void Configure(EntityTypeBuilder<InvoiceOverview> builder)
{
    builder.HasKey(_ => _.Id);
    builder.ToView("InvoiceOverview");

    builder.HasMany(_ => _.InvoiceLines)
        .WithOne()
        .HasForeignKey(_ => _.InvoiceId);

    if (MigrationHelper.IsMigrationOperationExecuting())
    {
        builder.Ignore(x => x.InvoiceLines);
    }
}

public static class MigrationHelper
{
    public static bool IsMigrationOperationExecuting()
    {
        var commandLineArguments = Environment.GetCommandLineArgs();
        string[] orderedMigrationArguments = { "migrations", "add" };

        for (var i = 0; i <= commandLineArguments.Length - orderedMigrationArguments.Length; i++)
        {
            if (commandLineArguments.Skip(i).Take(orderedMigrationArguments.Length).SequenceEqual(orderedMigrationArguments))
                return true;
        }

        return false;
    }
}