如何减少数量。访问导航属性时连接的列数?

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

我有一个基于 .net Web API 的项目,带有实体框架核心和 Azure Sql 数据库。

以下是我的数据模型,删除了额外的属性:

我在数据库上下文中有两个表,Parent 和 Children,具有父子关系。我为该类型提供了简单的名称来解释问题:

[Table("Parent")]
public record Parent
{
    [Key]
    public string ParentId { get; set; }

    public virtual ICollection<Children1> Children1s { get; set; }

    // other properties
}

[Table("Children1")]
public record Children1
{
    [Key]
    public string Children1Id { get; set; }

    [ForeignKey("ParentId")]
    public virtual Parent Parent { get; set; }

    public virtual ICollection<Children2> Children2s { get; set; }

    // many properties

}

我正在尝试获取所有父项目和链接的 Children1 项目,其中 Children1.另外,我还想为 Children1 获取 Children2。

我想为每个家长按日期(例如加入日期、上次/最近加入)订购的每个家长的其他孩子1中获取孩子1项目。

通过 Select 使用投影的方法中的存储库代码:

 var query = context.Parents
            .AsNoTracking()
            .Select(p => new
            {
                p.ParentId,
                p.Description,
                Children1s = d.Children1s
                .OrderByDescending(c => c.JoiningDate)
                .Take(1)
                .Select(c => new
                {
                    c.ChildrenId,
                    c.Description
                    // other properties
                }).ToList()
            });

使用

Include
ThenInclude
的方法中的存储库代码:

var result = context.Parents
            .AsNoTracking()
            .Include(d => d.Children1s
                .OrderByDescending(l => l.JoiningDate)
                .Take(1))
            .ThenInclude(l => l.Children2s)
            .ToList();

另外,我还在全球范围内使用

UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);

我的数据库有大约 20,000 条 Parent 记录,45,000 条 Children1 记录,大约 20,000 条 Children2 记录。

我还为用于 where、orderby 调用的每个表和字段都有索引。

Children1 大约有 200 列,这是一个旧表,我无法更改架构。

当我查看这两个选项生成的 SQL 时,即。通过投影和 Include,虽然我使用 select 只定位我需要的字段,但生成的 SQL 具有 Children1 中用于连接的所有字段 -

LEFT JOIN

由于此问题,Azure SQL 数据库中的查询非常慢。

如何控制EF只使用部分字段进行LEFT JOIN以加快查询速度?有/没有导航属性还有其他替代方法可以实现此目的吗?

似乎导航属性适合 1:1 关系,但由于 LEFT JOIN sql EF 生成,我需要对 1:n 关系执行的操作很慢。

我尝试了使用 Select 进行投影的各种方法,但我无法减少数量。用于连接的列。当我在线研究时,我了解了单一查询与拆分查询。所以,我现在使用后者,它稍微提高了性能。

c# entity-framework entity-framework-core azure-sql-database ef-core-8.0
1个回答
0
投票

您可以使用表拆分将数据库记录分区为两个或多个 EF Core 实体。 您可以通过共享主键来执行此操作 - 依赖实体的 PK 也是主体实体 PK 的 FK。 仅包含数据库中常用的字段作为主体实体中的属性,以最大限度地减少返回的字段。 当需要依赖实体中的字段时,您可以像添加任何其他导航属性一样简单地包含它们。

public class Principal
{
    public int Id { get; set; }
    public string PrincipalProperty { get; set; }
}

public class Dependent
{
    public int Id { get; set; }
    public string DependentProperty { get; set; }
}

// In OnModelCreating method
modelBuilder.Entity<Principal>( u =>
{
    u.ToTable("TableNameHere");
    ...
});

modelBuilder.Entity<Dependent>( u =>
{
    // use same table name
    u.ToTable("TableNameHere")
        .HasOne<Principal>()
        .WithOne()
        // dependent PK is the FK
        .HasForeignKey<Dependent>( d => d.Id );
});
© www.soinside.com 2019 - 2024. All rights reserved.