지원되지 않는 .Net Core 3.0 가능한 개체주기가 감지되었습니다.


22

일대 다로 관련된 2 개의 엔티티가 있습니다.

public class Restaurant {
   public int RestaurantId {get;set;}
   public string Name {get;set;}
   public List<Reservation> Reservations {get;set;}
   ...
}
public class Reservation{
   public int ReservationId {get;set;}
   public int RestaurantId {get;set;}
   public Restaurant Restaurant {get;set;}
}

내 API를 사용하여 예약 된 레스토랑을 얻으려고하면

   var restaurants =  await _dbContext.Restaurants
                .AsNoTracking()
                .AsQueryable()
                .Include(m => m.Reservations).ToListAsync();
    .....

객체에 서로 참조가 포함되어 있기 때문에 응답으로 오류가 발생합니다. 별도의 모델을 작성 하거나 NewtonsoftJson 구성을 추가 하도록 권장 하는 관련 게시물이 있습니다.

문제는 별도의 모델을 만들고 싶지 않으며 두 번째 제안이 도움이되지 않는다는 것입니다. 주기적인 관계없이 데이터를로드하는 방법이 있습니까? *

System.Text.Json.JsonException : 지원되지 않는 가능한 오브젝트주기가 발견되었습니다. 주기 때문이거나 오브젝트 깊이가 최대 허용 깊이 인 32보다 큽니다. System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializerCycleDetected (Int32 maxDepth)에서 System.Text.Json.JsonSerializer.Write (Utf8JsonWriter writer) System.Text.Json.JsonSerializer.WriteAsyncCore (Stream utf8Json, Object value, Type inputType, JsonSerializerOptions 옵션, CancellationToken CancellationToken)에서 System.Text.JsonSerializerOptions 옵션, WriteStack 및 state)의 Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions 옵션, WriteStack 및 상태). Microsoft.AspNetCore.Mvc에서 WriteResponseBodyAsync (OutputFormatterWriteContext 컨텍스트, Encoding selectedEncoding).

*


Reservation 클래스의 Restaurant 속성을 무시하도록 요청하십시오.
— Lasse V. Karlsen

6
실제로 API에서 직접 DB 엔터티를 반환해서는 안됩니다. API 별 DTO를 만들고 그에 따라 매핑하는 것이 좋습니다. 당신이 그렇게하고 싶지 않다고 말했지만 API와 지속성 내부를 분리하는 것이 일반적인 모범 사례라고 생각합니다.
— mackie

"그리고 두 번째 제안은 도움이되지 않았다"는 세부 사항이 필요하다.
— Henk Holterman

"문제는 별도의 모델을 만들고 싶지 않다는 것입니다." 그렇게하지 않으면 디자인에 근본적인 결함이 있습니다. API는 인터페이스와 같은 계약입니다 (문자 그대로 애플리케이션 프로그래밍 인터페이스 임). 게시 된 후에는 변경해서는 안되며, 모든 변경에는 새 버전이 필요하며 이전 버전과 동시에 실행해야합니다 (이는 더 이상 사용되지 않으며 향후 제거 될 예정 임). 이를 통해 클라이언트는 구현을 업데이트 할 수 있습니다. 엔터티를 직접 반환하면 데이터 계층이 밀접하게 연결됩니다.
— Chris Pratt

그런 다음 해당 데이터 계층을 변경하면 API를 즉시 되돌릴 수없는 변경이 필요하므로 구현을 업데이트 할 때까지 모든 클라이언트가 즉시 중단됩니다. 분명하지 않은 경우, 그것은 나쁜 것입니다. 한마디로 : API에서 엔터티를 수락하거나 반환하지 마십시오. 당신은해야한다 항상 DTO들을 사용합니다.
— Chris Pratt

답변:


32

새 프로젝트에서 코드를 시험해 보았고 두 번째 방법은 Microsoft.AspNetCore.Mvc.NewtonsoftJson 3.0을 처음 설치 한 후 잘 작동하는 것 같습니다

services.AddControllerWithViews()
    .AddNewtonsoftJson(options =>
    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);

새 프로젝트를 시도하고 차이점을 비교하십시오.


1
여기서 중요한 순간은 올바른 버전의 Microsoft.AspNetCore.Mvc.NewtonsoftJson을 다시 설치하는 것입니다.이 패키지는 오류 및 경고없이 상자에서 사용할 수 있으므로 버전에주의를 기울이지 않았습니다! 대답 해줘서 고마워요 ! 모든 것이 예상대로 작동합니다!
— Nazar Pylyp

1
시스템 json의 성능이 향상되면 NewtonsoftJson을 사용해야한다는 것이 잘못이 아닙니까? : /
— Marek Urbanowicz

40

.NET Core 3.1 Microsoft.AspNetCore.Mvc.NewtonsoftJson 패키지 설치

Startup.cs 서비스 추가

services.AddControllers().AddNewtonsoftJson(options =>
    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);

1
응답을 형식화하고 세부 사항을 추가 할 수 있습니까? 읽을 수 없습니다.
— 시드

자세한 내용은 다음을 확인하십시오 : thecodebuzz.com/…
— Diego Venâncio

4

시작시 JSON 직렬화 옵션을 설정하면 나중에 비슷한 경우가 발생할 수 있으므로 선호되는 방법 일 수 있습니다. 그러나 그 동안 모델에 데이터 속성을 추가하여 직렬화되지 않도록 할 수 있습니다. https://www.newtonsoft.com/json/help/html/PropertyJsonIgnore.htm

public class Reservation{ 
    public int ReservationId {get;set;} 
    public int RestaurantId {get;set;} 
    [JsonIgnore]
    public Restaurant Restaurant {get;set;} 
}

이것도 작동합니다. 그러나 언급했듯이 모든 모델을 업데이트해야하므로 services.AddControllers (). AddNewtonsoftJson (options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore)을 선호합니다.
— Nantharupan

1
public class Reservation{ 
public int ReservationId {get;set;} 
public int RestaurantId {get;set;} 
[JsonIgnore]
public Restaurant Restaurant {get;set;} 

위도 작동했습니다. 그러나 나는 다음을 선호한다

services.AddControllers().AddNewtonsoftJson(options =>
    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);

먼저 모든 모델에 속성을 추가해야하므로 순환 참조가있을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.