【问题标题】:ASP.net 6 Object Cycle was detected automapper nested list检测到 ASP.net 6 对象循环自动映射器嵌套列表
【发布时间】:2022-01-28 21:19:26
【问题描述】:

我目前正在从事一个个人项目,我想将UserTransaction 映射到GetAllTransactionRes 并在API/transaction 被击中时从我的数据库中返回所有UserTransaction。每次我使用API/transaction 端点时都会出现此错误

System.Collections.Generic.List`1[ProjectName.Modules.Transaction.Core.DTO.GetAllTransactionRes]
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles. Path: $.OrderedProducts.UserTransaction.OrderedProducts.UserTransaction.OrderedProducts.UserTransaction.OrderedProducts.UserTransaction.OrderedProducts.UserTransaction.OrderedProducts.UserTransaction.OrderedProducts.UserTransaction.OrderedProducts.UserTransaction.OrderedProducts.UserTransaction.OrderedProducts.UserTransaction.TransactionId.

这是UserTransaction 实体

    public class UserTransaction
    {
        public int TransactionId { get; set; }
        public DateTime Date { get; set; }

        public virtual ICollection<OrderedProduct> OrderedProducts { get; set; }
    }

这是Ordered Product 实体

    public class OrderedProduct
    {
        public int Id { get; set; }
        public string Product { get; set; }
        public int ProductId { get; set; }
        public int Quantity { get; set; }
        public bool Returned { get; set; }

        public int TransactionId { get; set; }
        public virtual UserTransaction UserTransaction { get; set; }
    }

这是我的映射器。 GetAllTransactionResAllOrderedProductDTOUserTransactionOrderedProduct 实体的精确副本。

CreateMap<UserTransaction, GetAllTransactionRes>().ForMember(s => s.OrderedProducts, c => c.MapFrom(m => m.OrderedProducts));
CreateMap<OrderedProduct, AllOrderedProductDTO>();

因为我使用的是 MediatR。这是我的 GetAllTransactionQuery 的处理程序

        public async Task<ICollection<GetAllTransactionRes>> Handle(GetAllTransactionQuery request, CancellationToken cancellationToken)
        {
            var Transactions = await _context.UserTransactions.Include(ut => ut.OrderedProducts).ToListAsync();
            var mapped = _mapper.Map<ICollection<UserTransaction>, ICollection<GetAllTransactionRes>>(Transactions);
            return mapped;
        }

在使用 automapper 之前,我使用了来自 efcore.include 方法,这给了我搜索答案时出现的相同错误,并且有人在 StackOverflow 问题中评论说我不应该直接在我的 API 中返回数据库实体。 This is the question where the said comment is posted

我做错了什么?谢谢

【问题讨论】:

    标签: c# .net entity-framework-core asp.net-core-webapi automapper


    【解决方案1】:

    我也有类似的问题。我通过添加装饰来解决这个问题。

    参考文档:https://docs.microsoft.com/en-us/ef/core/querying/related-data/serialization

    public class OrderedProduct
    {
        public int Id { get; set; }
        public string Product { get; set; }
        public int ProductId { get; set; }
        public int Quantity { get; set; }
        public bool Returned { get; set; }
    
        public int TransactionId { get; set; }
        [JsonIgnore]
        public virtual UserTransaction UserTransaction { get; set; }
    }
    

    【讨论】:

      【解决方案2】:

      问题在于您的 AllOrderedProductDTO 和您的 GetAllTransactionRes 数据传输对象具有循环引用 - 交易包含的产品包含包含产品的交易...

      以下是我建议打破循环的 DTO 类:

      public class GetAllTransactionRes
      {
          public int TransactionId { get; set; }
          public DateTime Date { get; set; }
          // be sure to use the products DTO here and not the entity because the entity has the loop
          public virtual ICollection<AllOrderedProductDTO> OrderedProducts { get; set; }
      }
      
      public class AllOrderedProductDTO
      {
          public int Id { get; set; }
          public string Product { get; set; }
          public int ProductId { get; set; }
          public int Quantity { get; set; }
          public bool Returned { get; set; }
      
          public int TransactionId { get; set; }
          // do not include the transaction entity or DTO here so that we avoid the loop
          //public virtual UserTransaction UserTransaction { get; set; }
      }
      

      【讨论】:

      • 您甚至可以从所有订购的产品 DTO 中删除交易 ID,因为产品嵌套在交易 DTO 中。
      • 可以忽略自动映射器配置中的 UserTransation 解决问题吗?
      • @knile - 是的,这也可以,但只要这些 DTO 配置了地图,您就必须设置忽略。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-26
      • 2021-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-12
      相关资源
      最近更新 更多