我正在尝试通过 JSON 上的 WCF Web 服务公开我的数据模型(代码优先实体框架)。该模型具有多个多对多关系并启用了延迟加载。我们的 Web 服务应该能够只返回多个子对象的第一级。我继续收到以下错误:
“无法评估表达式,因为当前线程处于堆栈溢出状态。”
我意识到在序列化具有循环引用的数据时会发生此错误。
在阅读了另一个线程后,我尝试了以下补救措施来处理循环引用:
- WCF 和 DataContractSerializer:使用 DataContract[IsReference=true] 显式标记您的实体,并使用 [DataMember] 属性显式标记所有属性。这将允许您使用循环引用。如果您使用 T4 模板生成实体,则必须对其进行修改以添加这些属性。
- WCF 和 DataContractSerializer:隐式序列化。使用 [IgnoreDataMember] 属性标记相关导航属性之一,以便不序列化属性。
- XmlSerializer:用 [XmlIgnore] 属性标记一个相关的导航属性
- 其他序列化:用 [NonSerialized] 标记一个相关的导航属性(Haz 他是第一个提到这一点的 +1)用于常见的序列化或 [ScriptIgnore] 用于一些 JSON 相关的序列化。
这些不同的方法都没有奏效。我真正需要的只是子对象的第一级。我不需要孩子的孩子这么说。我添加了以下代码来手动中断对第一级子对象的子对象的引用,这有效但不是有效的解决方案:
[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;
}
我正在寻找一种可靠的方法来处理通过 WCF 公开的 EF 中具有多对多关系的对象的序列化 - 或者 - 只是为了打破第一级子级以下的引用。我愿意以某种方式更改数据模型或重新配置 Web 服务。
为了完整起见,下面列出了我的所有相关代码:
[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();
}