EF Core 8 计数多对多关系生成错误查询

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

我正在使用 SQL Server 2019 和 EF Core 8。

我有两个实体,

TenantOrganization
(组织)和
SharedIndustry
(行业),它们通过加入实体
TenantOrganizationIndustries
(组织行业)具有多对多关系。从行业的 ID 开始,我想计算与其相关的 OrganizationIndustries 的数量,以便我可以允许或拒绝删除该行业。
Shared
Tenant
是数据库中的模式。

我遇到的问题是 EF Core 生成了错误的查询,并且错误地命名了查询中联接中的表。具体来说,它将

[Tenant].[Organizations]
命名为
[TenantOrganization]
,忽略名称的架构部分,并将表的名称单数化。

这是正在生成的查询:

SELECT TOP(1) (
    SELECT COUNT(*)
    FROM [Tenant].[OrganizationIndustries] AS [o]
    INNER JOIN [TenantOrganization] AS [t] ON [o].[OrganizationId] = [t].[Id]-- WRONG table name
    WHERE [i].[Id] = [o].[IndustryId])
FROM [Shared].[Industries] AS [i]
WHERE [i].[Id] = @__command_Id_0

查询的正确版本是这样的(根据我的口味重新格式化):

SELECT TOP(1)   (
                    SELECT  COUNT(*)
                    FROM    [Tenant].[OrganizationIndustries] AS [TOI]
                            INNER JOIN [Tenant].[Organizations] AS [TO] ON ([TOI].[OrganizationId] = [TO].[Id])-- CORRECT table name
                    WHERE   ([SI].[Id] = [TOI].[IndustryId])
                )
FROM            [Shared].[Industries] AS [SI]
WHERE           ([SI].[Id] = @__command_Id_0);

这是我正在使用的 LINQ 查询,用于创建生成的查询:

_shared.Industries.Where(i => i.Id == command.Id).Select(i => i.Organizations.Count).FirstAsync(cancellationToken)

这是

DbContext
中实体的导航配置:

builder.Entity<TenantOrganization>().HasMany(
    to => to.Industries).WithMany(
    si => si.Organizations).UsingEntity(
        "OrganizationIndustries",
        l => l.HasOne(typeof(SharedIndustry)).WithMany().HasForeignKey(nameof(TenantOrganizationIndustry.IndustryId)).HasPrincipalKey(nameof(SharedIndustry.Id)),
        r => r.HasOne(typeof(TenantOrganization)).WithMany().HasForeignKey(nameof(TenantOrganizationIndustry.OrganizationId)).HasPrincipalKey(nameof(TenantOrganization.Id)),
        j => j.ToTable("OrganizationIndustries", "Tenant"));

最后是 EF Core 模型:

public sealed class SharedIndustry {
    public SharedIndustryId Id { get; set; }
    public ICollection<TenantOrganization> Organizations { get; } = [];
}

public sealed class TenantOrganization {
    public TenantOrganizationId Id { get; set; }
    public ICollection<SharedIndustry> Industries { get; } = [];
}

public sealed class TenantOrganizationIndustry {
    public SharedIndustryId IndustryId { get; set; }
    public TenantOrganizationId OrganizationId { get; set; }
}

如何让 EF Core 生成正确的查询,特别是为表使用正确的名称?我这样做时没有使用

DbSet
来表示
TenantOrganizationIndustry
,但我开始怀疑我是否必须这样做才能使其发挥作用。

实际上,应该生成的最佳查询是:

SELECT  COUNT(*)
FROM    [Tenant].[OrganizationIndustries]
WHERE   ([IndustryId] = @__command_Id_0);

但我认为如果没有

DbSet
TenantOrganizationIndustry
我就无法做到。目前我想看看是否可以正确定义这个多对多连接,以便生成正确的查询。

如果能帮助实现这一目标,我们将不胜感激!

c# linq entity-framework-core ef-core-8.0
1个回答
0
投票

老实说,我不知道它最终如何工作,但我决定使用 EF Core Power Tools 对数据库进行逆向工程,看看它对多对多关系有何作用。在 Visual Studio 2022 中的 GUI 版本毫无进展后,我最终使用 CLI 版本对模型进行逆向工程,并复制了它为关系所做的配置。

值得注意的是,它应用了行业配置,而不是像我一样应用在组织上。我猜这只是因为它是按字母顺序排列的两个对象中的第一个。

我稍微调整了它,所以它不使用

Dictionary<string, object>
而是我的
TenantOrganizationIndustry
对象。这是当前工作版本:

builder.HasMany(
    si => si.Organizations).WithMany(
    to => to.Industries).UsingEntity<TenantOrganizationIndustry>(
    nameof(TenantOrganizationIndustry),
    r => r.HasOne<TenantOrganization>().WithMany().HasForeignKey(toi => toi.OrganizationId),
    l => l.HasOne<SharedIndustry>().WithMany().HasForeignKey(toi => toi.IndustryId),
    j => {
        j.ToTable("OrganizationIndustries", Schemas.Tenant).HasKey(toi => new {
            toi.IndustryId,
            toi.OrganizationId
        });

        j.Property(
            toi => toi.IndustryId).HasConversion<SharedIndustryId.EfCoreValueConverter>();

        j.Property(
            toi => toi.OrganizationId).HasConversion<TenantOrganizationId.EfCoreValueConverter>();
    });
© www.soinside.com 2019 - 2024. All rights reserved.