Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ef4导致web服务中的循环引用_C#_.net_Web Services_Entity Framework_Serialization - Fatal编程技术网

C# ef4导致web服务中的循环引用

C# ef4导致web服务中的循环引用,c#,.net,web-services,entity-framework,serialization,C#,.net,Web Services,Entity Framework,Serialization,我有一个理由: public class Reason { public virtual long Id { get; set; } public virtual string Name { get; set; } public virtual Company Company {get;set;} } 我使用的是实体框架4,公司是公司的导航属性。 我还使用Web服务将数据返回到客户端。 我有返回原因的web方法: [WebMethod] public Rea

我有一个理由:

public class Reason
{
    public virtual long Id { get; set; }
    public virtual string Name { get; set; }
    public virtual Company Company {get;set;}
}
我使用的是实体框架4,公司是公司的导航属性。
我还使用Web服务将数据返回到客户端。
我有返回原因的web方法:

  [WebMethod]
    public Reason[] GetCallReasons()
    {
        IReasonRepository rep =
            ObjectFactory.GetInstance<IReasonRepository>();
        return rep.GetReasonsList().ToArray();
    }
由于ef4添加了无法序列化的属性,因此出现了问题:

为了解决这个问题并消除错误,我可以通过不将导航属性设置为虚拟或删除导航属性来禁用它。但是我需要它,并且想要使用延迟加载特性

出于某种原因,我也可以编写spesific序列化程序,但我在web服务中使用了许多类,为所有这些类编写序列化程序需要大量的工作


如何解决此异常?。

您尚未提供公司类的定义。。。。但我猜你有很多理由

SOA环境中的延迟加载实际上不起作用。在序列化类上不能有无限的延迟导航,一旦离开webmethod,就无法从webmethod使用者调用原始datacontext来查找属性。。。因此,序列化程序将尝试访问所有属性,包括序列化时的惰性属性

您需要对循环引用的一部分禁用序列化,可以是对Company类中的Reason集合,也可以是Reason类中的Company


您可以使用“NotSerialized”属性来禁用特定字段的序列化。

我通常为Web服务编写特定的类。虽然这是一些额外的工作,但它的优点是Web服务变得更加健壮,因为实体中的小更改不会被忽略,并且不会在使用者/javascript方面悄无声息地失败。例如,如果我更改了属性的名称


您可以做一些事情来减少工作量,其中之一是使用AutoMapper,它可以在对象之间自动映射

您的问题有多种解决方案,它们实际上取决于您使用的服务类型和序列化类型:

  • 干净的方法是使用DTO(数据传输对象),正如@Mikael已经建议的那样。DTO是一种特殊的对象,它可以准确地传输您所需要的内容,仅此而已。您可以简单地创建不包含循环引用的DTO,并使用它在实体和DTO之间映射,反之亦然+因为他是第一个提到这一点的人
所有其他方法均基于@Haz建议的tweeking序列化:

  • WCF和
    DataContractSerializer
    :使用
    DataContract[IsReference=true]
    显式标记实体,并使用
    [DataMember]
    属性标记所有属性。这将允许您使用循环引用。如果您使用T4模板生成实体,则必须对其进行修改,以便为您添加这些属性
  • WCF和
    DataContractSerializer
    :隐式序列化。使用
    [IgnoreDataMember]
    属性标记一个相关导航属性,以便属性不会序列化
  • XmlSerializer
    :使用
    [XmlIgnore]
    属性标记一个相关导航属性
  • 其他序列化:使用
    [NonSerialized]
    标记一个相关的导航属性(Haz是第一个提到这一点的人,他是+1)用于普通序列化,或使用
    [ScriptIgnore]
    标记一些与JSON相关的序列化

这是一种多么痛苦的做法。至少你能做到。
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Reason_24A0E4BBE02EE6BC2CF30BB56CFCB670C7D9D96D03D40AF4D174B89C9D3C5537'