Thursday, May 5, 2011

IQueryable<> Serialization - C#-VS2008-WCF

I built my *.dbml file with the required tables and that generated the relationships, 1 to many.

One of my methods in my WCF Service library has this query

 IQueryable<Client>localClient = from c in db.Clients
              where c.ClientID.Equals(2612)
              select c;

 foreach(Client currentClient in localClient)
 {
    //Call serialize method here
 }

One of the table which client has a 1 to many relationships is Client - Employee

With 'localClient', I want to serialize that and return to the invoker. However it tells me that the the XML document could not be formed.

This is the InnerException: A circular reference was detected while serializing an object of type TestDB_Public.Employee.

My serialization code

    public string Serialize(object o, XmlSerializerNamespaces ns)
    {
        try
        {
            System.IO.MemoryStream m = new System.IO.MemoryStream();

            if (ns != null)
                serializer.Serialize(m, o, ns);
            else
                serializer.Serialize(m, o);

            m.Position = 0;
            byte[] b = new byte[m.Length];
            m.Read(b, 0, b.Length);

            return System.Text.UTF8Encoding.UTF8.GetString(b);
        }
        catch (Exception ex)
        {
            return "Ex = " + ex.ToString();
        }
    }

Is serialization of IQueryable<> with 1 to many relationships not possible?

From stackoverflow
  • What exactly is the error message? Note that you have to serialize something concrete like a list or array of objects (not a query).

    If you want queryable over the wire, look at ADO.NET Data Services, which does this.

    Also - have you set the serialization mode to "unidirectional" in the dbml designer? As long as there are no loops, it should work fine.

    Marc Gravell : The circular reference is the loop I was afraid of - for example, if an employee can see their manager, and the manager can see their subordinates, it gets into a state. However, you can enable the graph serialization mode of DataContractSerializer: http://chabster.blogspot.com/2008/02/wcf-cyclic-references-support.html or http://www.wearemappingyourdreams.com/andrew/ViewEntry.aspx?intLogId=1&intLogEntryId=622
  • Marc: For some reason it is not allowing me to add a comment;

    I added this

    [Table(Name="dbo.Client")]
    [DataContract(IsReference=true)]
    public partial class Client: INotifyPropertyChanging, INotifyPropertyChanged
    {
      ..//
      private EntitySet<ClEmp> _ClEmp;
    
      [Association(N...)]
      [DataMember(Order=70, EmitDefaultValue=false)]
      public EntitySet<ClEmp> ClEmps
    }
    

    My serialization is this:

    DataContractSerializer ser =
                        new DataContractSerializer(typeof(Client));
                    var ms = new System.IO.MemoryStream();
    
                    ser.WriteObject(ms, r);
    
                    ms.Seek(0, System.IO.SeekOrigin.Begin);
    
    
    
                    var sr = new System.IO.StreamReader(ms);
    
                    var xml = sr.ReadToEnd();
    

    when i look at var xml, i do not get my enity set ClEmp.

  • You can't serialise an object graph that has cyclical relationships:

    class Employee
    {
      Employee Manager;
      List<Employee> Employees;
    
    
    }
    
    
    var bossMan = new Employee();
    var emp2 = new Employee{Manager = bossMan}
    var bossMan.Employees.Add(emp2);
    

    If you now try to serialise bossman or emp2, you will get the exception.

    Have a look at this post, check the Cyclic Object Graphs for a solution.

0 comments:

Post a Comment