[英]How To Fix Query With Cycles Broken By Migration from EF Core 3 To EF Core 6
從 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");
});
}
如何解決?
在我看來,您要做的只是返回一個 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。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.