如何使用子表集合查询视图?

时间:2020-10-08 09:02:23

标签: c# ef-core-3.1

我想用EF Core 3.1中的子表集合查询视图。 以我的简化示例为例,其中包含3个表:

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();

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

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);
}

使用上述配置,我可以成功运行查询。 我现在遇到的唯一问题是,当我运行“添加迁移”时,他们想创建一个外键。无法为视图创建外键(并且该视图所使用的表上已存在外键)。

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

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

1 个答案:

答案 0 :(得分:0)

我在Entity Framework Core 2.2 : Disable migrations for specific entities找到了解决方案

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;
    }
}