0
votes

Brand new to WCF. Could really use some help.

I have a List of (100) objects, with 4 data members. DM1, DM2, DM3, DM4

I have a nest of datacontracts

DC1
 List<DC2>

DC2
 <DM1 Value=n> (n could be any number below 5, so there could be up to 5 DC2 inside the List in DC1)
 List<DC3>

DC3
 <DM2 value=n> (n could be any number below 10, so up to 10 DC3 inside the List in DC2)
 List<DC4>

DC4
 <DM3>
 <DM4>

Need to iterate through the original list of objects, and create one datacontract (DC1) with the various nested datacontracts, depending upon the different values within the datamembers of the original list of objects.

e.g.:

<DC1>
  <DC2>
    <DM1 value = "a">
    <DC3>
      <DM2 value = 1>
      <DC4>
        <DM3>
        <DM4>
      <DM2 value = 2>
      <DC4>
        <DM3>
        <DM4>
      <DC4>
        <DM3>
        <DM4>
    </D3>
  </DC2>
  <DC2>
    <DM1 value = "b">
    <DC3>
      <DM2 value = 1>
      <DC4>
        <DM3>
        <DM4>
      <DM2 value = 2>
      <DC4>
        <DM3>
        <DM4>
      <DC4>
        <DM3>
        <DM4>
    </D3>
  </DC2>
<DC1>

What's the best way of doing this?

Thanks!

Here's the DataContracts along with the service contract using DC1 to pass along the info:

[DataContract]
public class DC1
{
    [DataMember]
    public string string { get; set; }

    [DataMember]
    public List<DC2> LDC2{ get; set; }
}

[DataContract] public class DC2 { [DataMember] public string Type{ get; set; }

    [DataMember]
    public List<DC3> DC3s{ get; set; }

[DataContract] public class DC3 { [DataMember] public decimal num { get; set; }

    [DataMember]
    public List<DC4> DC4s{ get; set; }

[DataContract] public class DC4 { [DataMember] public int num2{ get; set; }

    [DataMember]
    public decimal Val{get; set;}

Service Contract: [ServiceContract(Namespace = Constants.Namespace)] public class Service {

    [OperationContract]
    DC1 GetMethod(int num);

DataSet:

is a LIST<> of the following object:

[Serializable]
public class Data
{
    public string Type { get; set; }
    public double Num { get; set; }
    public double Num2{ get; set; }
    public decimal Val{ get; set; }

}

Can have 100 (or more) of these objects in this list. With up to 5 types, with up to 10 of Num, and up to 5 of Num2.

Thanks for the response, and hope this clarifies!

1
Can you please explain a little more of what you are trying to accomplish? Possibly even some code for your current classes and how you've decorated them with [DataContract] and [DataMember] attributes. Because what you're asking seems like something WCF already does implicitly if you had a [OperationContract] method with class DC1 defined as your input or output.Sybeus
Thanks for the response. Edited the question with more code for clarity!user1771591

1 Answers

1
votes

There's probably more efficient ways than letting LINQ do all the work. However, this appears to be a question on how to convert de-normalized data into normalized objects, so GroupBy jumped out as an easy to code solution.

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace WcfTestService
{
    [ServiceContract]
    public interface ISoapService
    {
        [OperationContract]
        DC1 GetDC1();
    }

    public class SoapService : ISoapService
    {
        public DC1 GetDC1()
        {
            // Example dataset
            var dataset = new List<Data>()
            {
                new Data() { Type = "a", Num = 1, Num2 = 1, Val = 41.00m },
                new Data() { Type = "a", Num = 2, Num2 = 1, Val = 42.00m },
                new Data() { Type = "a", Num = 2, Num2 = 2, Val = 43.00m },
                new Data() { Type = "b", Num = 1, Num2 = 1, Val = 44.00m },
                new Data() { Type = "b", Num = 2, Num2 = 1, Val = 45.00m },
                new Data() { Type = "b", Num = 2, Num2 = 2, Val = 46.00m },
            };

            // Process dataset into data contract objects
            return new DC1()
            {
                DC2s = dataset.GroupBy(x => x.Type).Select(typeGrouping => new DC2()
                {
                    DM1 = typeGrouping.Key,
                    DC3s = typeGrouping.GroupBy(x => x.Num).Select(numGrouping => new DC3()
                    {
                        DM2 = Convert.ToDecimal(numGrouping.Key),
                        DC4s = numGrouping.Select(x => new DC4()
                        {
                            DM3 = Convert.ToInt32(x.Num2),
                            DM4 = x.Val
                        }).OrderBy(x => x.DM3).ToList()
                    }).OrderBy(x => x.DM2).ToList()
                }).OrderBy(x => x.DM1).ToList()
            };
        }
    }

    [Serializable]
    public class Data
    {
        public string Type { get; set; }
        public double Num { get; set; }
        public double Num2 { get; set; }
        public decimal Val { get; set; }
    }

    [DataContract]
    public class DC1
    {
        [DataMember]
        public List<DC2> DC2s { get; set; }
    }

    [DataContract]
    public class DC2
    {
        [DataMember]
        public string DM1 { get; set; }
        [DataMember]
        public List<DC3> DC3s { get; set; }
    }

    [DataContract]
    public class DC3
    {
        [DataMember]
        public decimal DM2 { get; set; }
        [DataMember]
        public List<DC4> DC4s { get; set; }
    }

    [DataContract]
    public class DC4
    {
        [DataMember]
        public int DM3 { get; set; }
        [DataMember]
        public decimal DM4 { get; set; }
    }
}

The output of GetDC1() should be very close to your example output, but all WCF'ified.