XMLserializer,Entity Framework:无法序列化ICollection类型的成员,请参阅内部异常以获取更多详细信息

时间:2015-12-10 11:21:17

标签: asp.net xml entity-framework xml-serialization icollection

我想将XML元素映射到我的数据库表中(使用Entity Framework):

var xmlSerializer = new XmlSerializer(typeof(Participant), new XmlRootAttribute("participant"));
var participant = (Participant)xmlSerializer.Deserialize(new StringReader(content));

我有参与者表格,我可以通过

访问
[XmlRoot("participant", Namespace = "")]
    public partial class Participant
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage",     "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Participant()
        {
            this.GroupParticipant = new HashSet<GroupParticipant>();
            this.ParticipantAddress = new HashSet<ParticipantAddress>();
            this.ParticipantPublisher = new HashSet<ParticipantPublisher>();
            this.ParticipantJob = new HashSet<ParticipantJob>();
            this.ParticipantProvider = new HashSet<ParticipantProvider>();
        }
        [XmlElement("firstName")]
        public string FirstName { get; set; }

        [XmlElement("lastName")]
        public string LastName { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        //[XmlElement("address")]
        //[XmlElement("address")]
        //[XmlArray("HashSet<ParticipantAddress>"), XmlElement("address")]
        //[XmlArrayItem("ICollection<ParticipantAddress>")]
        //[XmlAttribute(DataType = "ICollection<ParticipantAddress>",  AttributeName = "address")]

[XmlElement("address", typeof(List<ParticipantAddress>))]
        public virtual ICollection<ParticipantAddress> ParticipantAddress { get; set; }
}

ParticipantAddress是ICollection:

[Serializable]
    [XmlInclude(typeof(HashSet<ParticipantAddress>))]
    public partial class ParticipantAddress
    {
        public int ParticipantAddressId { get; set; }
        public int ParticipantId { get; set; }

        [XmlElement("city")]
        public string City { get; set; }

        [XmlElement("state")]
        public string State { get; set; }

        [XmlElement("zipCode")]
        public string ZipCode { get; set; }

        public virtual Participant Participant { get; set; }
    }

例外说:

  

{“反映出类型为'x.Participant'的错误。”}

我的内心异常说:

  

{“无法序列化'System.Collections.Generic.ICollection`1 [[x.ParticipantAddress,APS.Data.BatchInterface,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]的成员'xParticipant.ParticipantAddress' ]]',请参阅内部异常以获取更多详细信息。“}

我正在通过streamReader阅读XML。

我试过了

  • [XMLArray]
  • 将ICollection更改为List
  • make class serializable

有没有其他方法可以解决此问题或与我的问题相关的任何示例或我需要在代码中实现的任何更改?

5 个答案:

答案 0 :(得分:0)

由于virtual属性,您遇到此问题。您尝试序列化一个类,该类具有对另一个类的引用,该类具有对第一个类的引用,其中......无限循环。

如果要序列化实体,您可以做的最好的事情是使用DTO类,这是一个仅用于导出数据的类。在这些类中,您不能拥有虚拟属性,但您可以执行的操作包括ParticipantAddress的DTO对象。

如果不需要序列化为XML,那么您可以尝试的另一件事是使用Newtonsoft.Json包来序列化实体。该软件包有一些处理导航属性的选项。

答案 1 :(得分:0)

ICollection不可序列化 - 您可以使用DTO - 您可以更改集合类型(即使用List&lt;&gt;)并使用XML序列化属性避免循环引用和/或禁用延迟加载(即使用Include方法急切加载)或风险是您序列化整个数据库。 / p>

答案 2 :(得分:0)

我创建了一个区域并更改了ICollection&lt;&gt;列出&lt;&gt;因为

  

ICollection是一个接口,接口不可序列化。

列表&lt;&gt;是一个类,这个类实现了以下所有接口: IList, ICollection ,IList,ICollection,IReadOnlyList,IReadOnlyCollection,IEnumerable,IEnumerable。

我保留了Icollection和List,并将[XmlIgnore]放在ICollection上。

    [XmlRoot("participant", Namespace = "")]
    public partial class Participant
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Participant()
        {
            this.GroupParticipantList = new List<GroupParticipant>();
            this.ParticipantAddressList = new List<ParticipantAddress>();
            this.ParticipantPublisherList = new List<ParticipantPublisher>();
            this.ParticipantJobList = new List<ParticipantJob>();
            this.ParticipantProviderList = new List<ParticipantProvider>();
        }

        [XmlElement("firstName")]
        public string FirstName { get; set; }

        [XmlElement("lastName")]
        public string LastName { get; set; }

        [XmlIgnore]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<ParticipantAddress> ParticipantAddress { get; set; }

        #region Custom properties

        [XmlElement("address")]
        public virtual List<ParticipantAddress> ParticipantAddressList { get; set; }

        #endregion
    }

但是使用这个选项我还有另一个问题:如果我在SQL数据库中进行任何单一更改,如果我从数据库更新模型,那么我将失去手动实现的代码,就像所有XML语句一样在这段代码中。

答案 3 :(得分:0)

我在下面的文章中回答了此问题,将[System.Xml.Serialization.XmlIgnore]添加到entity.tt模板

Prevent Property from being serialized

答案 4 :(得分:0)

我在使用 EF 实现 Web 服务时遇到了类似的事件,但无法序列化 ICollection<> 对象。 我希望这对您有所帮助。

public class User
{
    public User()
    {
        sessions = new HashSet<Session>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    [XmlIgnore]
    [IgnoreDataMember]
    public virtual ICollection<Session> sessions { get; set; }
}


public class Session
{
    public int Id { get; set; }
    public Datetime start_dtime{ get; set; }
    public Datetime end_dtime{ get; set; }

    public virtual User user{ get; set; }
}