简体   繁体   English

如何修复从 EF Core 3 迁移到 EF Core 6 导致循环中断的查询

[英]How To Fix Query With Cycles Broken By Migration from EF Core 3 To EF Core 6

After migration from EF Core 3 to EF Core 6 this query:从 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);
}

started to throw error:开始抛出错误:

System.InvalidOperationException: A tracking query is attempting to project an owned entity without a corresponding owner in its result, but owned entities cannot be tracked without their owner. System.InvalidOperationException:跟踪查询正在尝试在其结果中投影没有相应所有者的自有实体,但如果没有其所有者,则无法跟踪自有实体。 Either include the owner entity in the result or make the query non-tracking using 'AsNoTracking'.要么在结果中包含所有者实体,要么使用“AsNoTracking”使查询不跟踪。

Changing to 'AsNoTracking()' gives another error:更改为“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: The Include path 'MetaProduct->Variations' results in a cycle. System.InvalidOperationException:包含路径“MetaProduct->Variations”导致循环。 Cycles are not allowed in no-tracking queries;无跟踪查询中不允许循环; either use a tracking query or remove the cycle.使用跟踪查询或删除循环。

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

Relationship configuration:关系配置:

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

How to fix it?如何解决?

It seems to me that all you're trying to do is return an array of Variations where the Variation Id is in the list.在我看来,您要做的只是返回一个 Variations 数组,其中 Variation Id 在列表中。

Also, your variation should not have a navigation property back to MetaProduct when it is owned.此外,您的变体在拥有时不应具有返回 MetaProduct 的导航属性。 It should really only be retrieved in the context of its owner.它实际上应该只在其所有者的上下文中检索。

If you really want to navigate from Variation to MetaProduct then you should reconsider whether Variation really is an 'owned' entity or just a related entity.如果您真的想从 Variation 导航到 MetaProduct,那么您应该重新考虑 Variation 是否真的是一个“拥有”实体或只是一个相关实体。

The problem is that you are entering the query from MetaProducts but then trying to Include it again.问题是您正在从 MetaProducts 输入查询,但随后尝试再次包含它。 If you can do away with the navigation from Variation to MetaProduct then the following will work:如果您可以取消从 Variation 到 MetaProduct 的导航,那么以下操作将起作用:

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

If you really want to navigate the other way, then you'd need to promote Variation to a related entity (HasMany instead of OwnsMany), and then expose Variations as a DbSet on your context.如果您真的想以另一种方式导航,那么您需要将 Variation 提升为相关实体(HasMany 而不是 OwnsMany),然后在您的上下文中将 Variations 公开为 DbSet。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM