2

JSON을 통해 WCF 웹 서비스를 통해 데이터 모델 (코드 첫 번째 엔터티 프레임 워크)을 노출하려고합니다. 모델은 다 대다 관계를 여러 개 갖고 있으며 느린 로딩을 사용할 수 있습니다. 우리의 웹 서비스는 여러 자식 객체의 첫 번째 수준 만 반환 할 수 있어야합니다. 다음 오류가 계속 나타납니다.순환 참조 처리 방법 - 또는 - Entity Framework 데이터 모델을 노출하는 WCF 서비스에서 반환 된 첫 번째 수준 하위 참조를 끊으시겠습니까?

"현재 스레드가 스택 오버플로 상태에 있기 때문에 식을 계산할 수 없습니다."

이 오류는 순환 참조가있는 데이터를 serialize 할 때 발생한다는 것을 알고 있습니다.

  • WCF 및 DataContractSerializer : 명시 적으로 DataContract [IsReference = TRUE] 및 [DataMember를] 속성을 가진 모든 속성으로 개체를 표시

    다른 스레드를 읽은 후 나는 순환 참조를 처리하기 위해 다음과 같은 치료를 시도 . 이렇게하면 순환 참조를 사용할 수 있습니다. 이 T4 템플릿을 사용하여 엔티티를 생성하는 경우이를 수정하여 속성을 추가해야합니다.

  • WCF 및 DataContractSerializer : 암시 적 serialization. [IgnoreDataMember] 특성을 사용하여 관련 탐색 속성 중 하나를 표시하면 속성이 직렬화되지 않습니다.
  • XmlSerializer는 : 표시 한 관련 탐색 특성 FO 으로는 [XmlIgnore]
  • 다른 직렬화 특성 : 공통 대한 관련 탐색 등록 마크를 [NonSerialized]와 (그는이 언급 제 하즈 대한 +1 WAS) 직렬화 또는 일부 JSON 관련 [ScriptIgnore] 직렬화.

이러한 접근 방식 중 어느 것도 효과가 없습니다. 제가 정말로 필요로하는 것은 아이들 오브젝트의 첫 단계입니다. 나는 아이들의 아이들이 말할 필요가 없다. 나는 수동으로 첫 번째 수준 자식의 자식 개체에 대한 참조를 중단하려면 다음 코드를 추가하고,이 일을하지만, 올바른 해결책이 아니다 :

[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetReportTypes")] 
    public List<ReportType> GetReportTypes() 
    { 
     List<ReportType> result = BusinessLogic.GetReportTypes(_context).ToList(); 
     foreach (var x in result) 
     { 
      foreach (var y in x.Sections) 
      { 
       y.ReportType = null; 
      } 

     }; 
     return result; 
    } 

나는 개체의 직렬화 처리에 고체 방법을 찾고 있어요 EF에서 WCF를 통해 노출 된 다 대 다 관계가 있습니다. 또는 단순히 첫 번째 수준 하위의 참조를 깨기위한 것입니다. 나는 데이터 모델을 변경하거나 웹 서비스를 어떻게 든 재구성 할 수있다. 당신이 게으른 로딩을 끄고 아이들의 실체 단지 첫 번째 레벨을로드하는 열망로드를 사용해야합니다 단지 하나의 레벨을 원하는 경우

[DataContract(IsReference = true)] 
[Table("ReportType", Schema = "Reporting")] 
public class ReportType 
{ 
    [Key] 
    [Column("ID")] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    [DataMember] 
    public int Id { get; set; } 

    [DataMember] 
    public virtual ICollection<ReportTypeSection> Sections { get; set; } 
} 


[Table("Section", Schema = "Reporting")] 
[DataContract(IsReference = true)] 
public class Section 
{ 
    [Key] 
    [Column("ID")] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    [DataMember] 
    public int Id { get; set; } 

    [DataMember] 
    public virtual ICollection<ReportTypeSection> ReportTypes { get; set; } 
} 

[Table("ReportTypeSection", Schema = "Reporting")] 
[DataContract(IsReference=true)] 
public class ReportTypeSection 
{ 
    [Column("ID")] 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    [DataMember] 
    public int Id { get; set; } 

    [Column("ReportTypeID")] 
    [Required(ErrorMessage = "Report Type Section Foreign Key Report Type ID is Required")] 
    [DataMember] 
    public int ReportTypeId { get; set; } 

    [Column("SectionID")] 
    [Required(ErrorMessage = "Report Type Section Foreign Key Section ID is Required")] 
    [DataMember] 
    public int SectionId { get; set; } 

    [DataMember] 
    public virtual ReportType ReportType { get; set; } 

    [DataMember] 
    public virtual Section Section { get; set; } 

} 

public class BusinessLogic 
{ 
    public static IEnumerable<ReportType> GetReportTypes(IDatabaseContext context) 
    { 
     IEnumerable<ReportType> result = context.ReportTypes 
      .Include(a => a.Sections) 
      .AsEnumerable(); 
     return result; 
    } 
} 

public class ReportConfigurationService : IReportConfigurationService 
{ 
    private IEmspeedDatabaseContext _context; 
    public ReportConfigurationService(IEmspeedDatabaseContext context) 
    { 
     _context = context; 
    } 

    [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetReportTypes")] 
    public List<ReportType> GetReportTypes() 
    { 
     List<ReportType> result = BusinessLogic.GetReportTypes(_context).ToList(); 
     return result; 
    } 
} 

[ServiceContract] 
public interface IReportConfigurationService 
{ 

    [OperationContract] 
    [ApplyDataContractResolver] 
    List<ReportType> GetReportTypes(); 
} 

답변

2

: 아래의 완성도를 들어

내 관련 모든 코드입니다. 그러한 네비게이션 프로퍼티가 존재하는 경우에도 자식에서 부모로의 역방향 직렬화가 여전히 발생할 수 있습니다. 모든 직렬화 문제를 완전히 피하려면 사용하려는 데이터 및 단방향 관계 만 모델링하는 DTO (데이터 전송 객체)를 사용해야합니다. DTO를 서비스 조작으로 채우고 반환하면 DTO를 구성하여 직렬화를 완벽하게 제어 할 수 있습니다.이 DTO는 엔티티 모델과 독립적입니다.

0

그냥 (I 열심히 로딩을 사용하는이 경우)를 ciclic 참조가 재산을 통해 [DataMember를] 속성을 넣어 피하기 :

[DataContract] 
public class Persona 
{ 
    [DataMember] 
    [Key] 
    public int IdPersona { get; set; } 
    [DataMember] 
    public string Nombre { get; set; } 
    [DataMember] 
    public List<Domicilio> Domicilios { get; set; } 
} 

[DataContract] 
public class Domicilio 
{ 
    [DataMember] 
    [Key] 
    public int IdDomicilio { get; set; } 
    [DataMember] 

    public Persona persona { get; set; } 
}