1

I want to map XML elements into my database table (using Entity Framework):

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

I have Participant table which I can access by

[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 is 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; }
    }

Exception says:

{"There was an error reflecting type 'x.Participant'."}

My inner Exception says:

{"Cannot serialize member 'xParticipant.ParticipantAddress' of type 'System.Collections.Generic.ICollection`1[[x.ParticipantAddress, APS.Data.BatchInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]', see inner exception for more details."}

I am reading XML by streamReader.

I have tried

  • [XMLArray]
  • Changing ICollection to List
  • make class serializable

Is there any other way to overcome this problem or any examples related to my question or any changes I need to implement in my code?

halfer
  • 19,824
  • 17
  • 99
  • 186
Riddhi
  • 202
  • 5
  • 17

5 Answers5

0

You have this issue because of the virtual properties. You try to serialize a class which has a reference to another class, which has a reference to the first, class, which... endless loop.

If you want to serialize an entity, the best thing you can do is use a DTO class, which is a class used only to export your data. In these classes you can't have virtual properties, but what you can do is include the DTO objects of your ParticipantAddress.

The other thing you can try, if it isn't a necessity to serialize to XML, is use the Newtonsoft.Json package to serialize the entities. The package has some options to deal with navigational properties.

Alexander Derck
  • 13,818
  • 5
  • 54
  • 76
0

ICollection is not serializable.
- You can use DTO.
- You can change the collection type (i.e. with List<>) and with XML serialization attributes avoid circular references and/or disable lazy load (i.e. use eagerly load using Include method) or the risk is that you serialize the whole database.

bubi
  • 6,414
  • 3
  • 28
  • 45
  • Thanks for your help. I have created a region and change the collection type ICollection<> to List<> because ICollection is an interface and interfaces are not serializable. But List<> is a class and this class implements all the below interfaces: IList, ICollection, IList, ICollection, IReadOnlyList, IReadOnlyCollection, IEnumerable, IEnumerable. – Riddhi Dec 14 '15 at 09:59
0

I have created a region and change ICollection<> to List<> because

ICollection is an interface and interfaces are not serializable.

But List<> is a class and this class implements all the below interfaces: IList, ICollection, IList, ICollection, IReadOnlyList, IReadOnlyCollection, IEnumerable, IEnumerable.

I kept both Icollection as well as List and put [XmlIgnore] on 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
    }

But with this option I am having another Problem: If I do any single change in my SQL database and if I do update model from database, then I lose manually implemented code like all the XML sentences in this code.

Riddhi
  • 202
  • 5
  • 17
0

I answered this in the below article to add [System.Xml.Serialization.XmlIgnore] to entity.tt template

Prevent Property from being serialized

0

I had a similar issue using EF, to implement a Web service and couldn't serialize the ICollection<> object. I hopes this helps you out.

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; }
}
Shahid Rasheed
  • 371
  • 4
  • 10