0

从 EF Core 3 迁移到 EF Core 6 后,此查询:

private async Task<Variation[]> GetPizzasInOrder(Uuid[] productsInOrder, CancellationToken ct)
{
    return await _clientCheckupsGatewayContext.MetaProducts
        .SelectMany(mp => mp.Variations)
        .Where(v => productsInOrder.Contains(v.Id))
        .Include(v => v.MetaProduct)
        .ToArrayAsync(ct);
}

开始抛出错误:

System.InvalidOperationException:跟踪查询正在尝试在其结果中投影没有相应所有者的自有实体,但如果没有其所有者,则无法跟踪自有实体。要么在结果中包含所有者实体,要么使用“AsNoTracking”使查询不跟踪。

更改为“AsNoTracking()”会产生另一个错误:

private async Task<Variation[]> GetPizzasInOrder(Uuid[] productsInOrder, CancellationToken ct)
{
    return await _clientCheckupsGatewayContext.MetaProducts
        .AsNoTracking()
        .SelectMany(mp => mp.Variations)
        .Where(v => productsInOrder.Contains(v.Id))
        .Include(v => v.MetaProduct)
        .ToArrayAsync(ct);
}

System.InvalidOperationException:包含路径“MetaProduct->Variations”导致循环。无跟踪查询中不允许循环;使用跟踪查询或删除循环。

public class MetaProduct
{
    public Uuid Id { get; }
    public IReadOnlyList<Variation> Variations => _variations.ToArray();
    private List<Variation> _variations = null!;
}

public class Variation
{
    public Uuid Id { get; }

    public MetaProduct? MetaProduct { get; }
}

关系配置:

private static void MapMetaProducts(ModelBuilder modelBuilder)
{
    var tagsConverter = new ValueConverter<string[], string>(
        v => JsonConvert.SerializeObject(v),
        v => JsonConvert.DeserializeObject<string[]>(v)
    );

    var builder = modelBuilder.Entity<MetaProduct>().ToTable("metaproducts");
    builder.HasKey(p => p.Id);

    builder.Property(p => p.Id).HasColumnName("Id");

    builder.OwnsMany(mp => mp.Variations,
        vBuilder =>
        {
            vBuilder.ToTable("metaproducts_variations");

            vBuilder.WithOwner(v => v.MetaProduct!);

            vBuilder.Property(v => v.Id).HasColumnName("Id");

            vBuilder.HasKey("Id");
        });
}

如何解决?

4

1 回答 1

0

在我看来,您要做的只是返回一个 Variations 数组,其中 Variation Id 在列表中。

此外,您的变体在拥有时不应具有返回 MetaProduct 的导航属性。它实际上应该只在其所有者的上下文中检索。

如果您真的想从 Variation 导航到 MetaProduct,那么您应该重新考虑 Variation 是否真的是一个“拥有”实体或只是一个相关实体。

问题是您正在从 MetaProducts 输入查询,但随后尝试再次包含它。如果您可以取消从 Variation 到 MetaProduct 的导航,那么以下操作将起作用:

return await _clientCheckupsGatewayContext.MetaProducts
    .AsNoTracking()
    .SelectMany(mp => mp.Variations)
    .Where(v => productsInOrder.Contains(v.Id))
    .ToArrayAsync(ct);

如果您真的想以另一种方式导航,那么您需要将 Variation 提升为相关实体(HasMany 而不是 OwnsMany),然后在您的上下文中将 Variations 公开为 DbSet。

于 2021-11-19T21:10:18.227 回答