我有两个从EF自动生成的简单列表:
public partial class Visitor
{
public Visitor()
{
this.Visits = new HashSet<Visit>();
}
public int Id { get; set; }
public int PermitId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public bool IsValid { get; set; }
public System.DateTime RegistrationDate { get; set; }
public byte[] Picture { get; set; }
public virtual ICollection<Visit> Visits { get; set; }
}
public partial class Visit
{
public int Id { get; set; }
public int VisitType { get; set; }
public System.DateTime VisitDate { get; set; }
public Nullable<int> Visitor_Id { get; set; }
public virtual Visitor Visitor { get; set; }
}
在WCF方法中,我尝试返回以下结果:
[Serializable]
[DataContract(IsReference = true)]
[KnownType(typeof(Visitor))]
[KnownType(typeof(Visit))]
[KnownType(typeof(ICollection<Visit>))]
public class ServiceVisit : IServiceVisit
{
public List<Visitor> AllVisitors()
{
using (var te = new TurnstileDbEntities())
{
te.Configuration.ProxyCreationEnabled = false;
return te.Visitors.Include("Visits").ToList();
}
}
}
但我收到了一个例外:
尝试序列化参数时出错 http://tempuri.org/:AllVisitorsResult。消息InnerException“对象 类型图 “System.Collections.Generic.HashSet`1 [[TurnstileWcfService.Visit, TurnstileWcfService,Version = 1.0.0.0,Culture = neutral, PublicKeyToken = null]]“包含循环,如果是,则无法序列化 参考跟踪已禁用“。
在所有类似的胎面中建议这样做:
[DataContract(IsReference = true)]
或使用第三方序列化库(Newtonsoft.Json)。但这不是我的选择。因为我不想在WinForms应用程序中使用Json。 我该如何解决这个问题以及其他解决方案呢?
答案 0 :(得分:0)
一个老问题,但我已多次遇到这个问题,可以通过以下解决方案解决:
[IgnoreDataMember]
字面上忽略了该成员,.Include
突然没有意义。
应为每个类而不是服务添加[Serializable]
,[DataContact...]
和[KnownType(typeo...)]
属性:
XAML:
[Serializable]
[DataContract(IsReference = true)]
[KnownType(typeof(Visit))]
public partial class Visit
{
public int Id { get; set; }
public int VisitType { get; set; }
public System.DateTime VisitDate { get; set; }
public Nullable<int> Visitor_Id { get; set; }
public virtual Visitor Visitor { get; set; }
}
但是,由于您的类是自动生成的,因此您必须将这些修改添加到模板文件中。
取决于您所谓的模型,会有一个.tt
文件。就我而言PolModel.tt
。
在.tt文件中找到<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
行,然后添加:
using System.Runtime.Serialization;
之后:
[Serializable]
[DataContract(IsReference = true)]
[KnownType(typeof(<#=code.Escape(entity)#>))]
当您参与其中并进行此修改时,您还应考虑将[DataMember]
属性添加到properties
,否则它们将无法使用。
[Serializable]
[DataContract(IsReference = true)]
[KnownType(typeof(Visit))]
public partial class Visit
{
[DataMember]
public int Id { get; set; }
[DataMember]
public int VisitType { get; set; }
[DataMember]
public System.DateTime VisitDate { get; set; }
[DataMember]
public Nullable<int> Visitor_Id { get; set; }
[DataMember]
public virtual Visitor Visitor { get; set; }
}
答案 1 :(得分:0)
这是由于EF使用Include时的工作方式。父项具有对子项的引用,子项具有对父项的引用。 WCF将永远陷入两者之间。如果您希望它正确序列化,只需通过将子项设置为null来删除子项上的所有父引用。然后循环引用消失了。否则,您需要建立自己的模型,并从EF模型中选择您真正想要的,这样您就知道您没有返回无限循环。不直接暴露EF实体的另一个原因。 :)