Posted on 2009-07-11
Last Modified: 2013-11-11
Any WCF/LINQ experts out there?  I'm having a heck of a time getting my relational data to pass through WCF.

First off, I tried all of this through straight LINQ to SQL and was getting some error regarding a circular reference, which I found puzzling as I didn't see a circular reference in my db.  After fighting with LINQ to SQL I moved on to trying PLINQO and the circular error went away, however the nested Lists of entities won't transmit properly.

I have several tables in my db but the 2 currently in question are CustomersVendors and Addresses.  The addresses are linked to the CustomersVendors table via listID <--- customerVendorListID and the 2 columns are identical.  When I request a CustomerVendor by listID I expect to get back all of their details including a List(Of Addresses).  Upon tracing the results I see the query works just fine and I do in fact see the Addresses in the CustomersVendors entity.  The problem is, once this data is sent out via WCF the Addresses entity inside of the CustomerVendor is NULL.  Tracelogs on the server side of my app don't show the addresses so they are obviously never leaving the server.  I'm guessing it's a serialization issue but I'm at the end of my rope trying to find the cause.  I sure hope someone out there can figure this one out.

vs2008 SP1 (VB.NET)
.NET 3.5 SP1
Vista Business SP3
PLINQO v3.0.687
Question by:thesnoman
  • 2
LVL 62

Expert Comment

by:Fernando Soto
ID: 24830397
Hi thesnoman;

I am not a WCF expert but you seem to be on the right track about serialization. Linq by default sets the Serialization Mode to none. In WCF applications it should be set to Unidirectional which will allow the child records to come across as well. To set the DataContext for this setting do the following.

1. Open the OR/M designer and right click on the design surface where there are NO tables.
2. Select Properties in the context menu.
3. Select the Serialization Mode property and in its combo box select Unidirectional.

Hopefully this will do it.


Author Comment

ID: 24830985
Thanks for the reply Fernando,

I've actually tried that and it didn't help.  I've not found a true solution yet so for now what I've done is remove all relationships from the db and create wrappers for sending the data, as shown in the code snippet.  This works fine but it adds a fair amount of code and time to parse.  I'm not yet sure what I'm going to run into for saving but I'm sure it's going to be a lot more work.  It's a shame when something that's supposed to save us time costs us a lot more.  If you or anyone else has anymore ideas please pass them along as I'd be glad to hear them.

Custom Wrapper:

<DataContract()> _

Public Class twCustomerVendor

    Private _customerVendor As CustomersVendor

    Private _addresses As List(Of Address)

    Private _contacts As List(Of Contact)

    <DataMember()> _

    Public Property CustomerVendor() As CustomersVendor


            Return Me._customerVendor

        End Get

        Set(ByVal value As CustomersVendor)

            Me._customerVendor = value

        End Set

    End Property

    <DataMember()> _

Public Property Addresses() As List(Of Address)


            Return Me._addresses

        End Get

        Set(ByVal value As List(Of Address))

            Me._addresses = value

        End Set

    End Property

    <DataMember()> _

Public Property Contacts() As List(Of Contact)


            Return Me._contacts

        End Get

        Set(ByVal value As List(Of Contact))

            Me._contacts = value

        End Set

    End Property

End Class

Then I populate it as follows:

Public Function GetCustomerVendor(ByVal ListID As Integer) As twCustomerVendor

    Dim Context As New OxionIt2DataContext

    Dim ret As New twCustomerVendor

    ret.CustomerVendor = (From cv In Context.CustomersVendor _

                          Where cv.ListID = ListID _

                          Select cv).SingleOrDefault

    ret.Addresses = (From a In Context.Address _

                     Where a.CustomerVendorListID = ret.CustomerVendor.ListID _

                     Select a).ToList

    ret.Contacts = (From c In Context.Contact _

                    Where c.CustomerVendorListID = ret.CustomerVendor.ListID _

                    Select c).ToList

    Return ret

End Function

Open in new window


Accepted Solution

thesnoman earned 0 total points
ID: 24835817
For future reference I found the solution.  It is not a WCF serialization issue as first suspected rather it part of LINQ's lazy loading technique.  While I knew this existed I did not know that at the time of loading the parent it does not actually load all the related children as I would have expected.  There is a way to get around this issue and it involves LINQ's "DataLoadOptions" command.  This forces LINQ to load all the related info when the parent record is loaded.  This can also be a good thing to minimize the number of queries made against the database.  

Here is a sample of my code in VB that may save someone else hours/days of research, troubleshooting, and heartache.  Notice DataLoadOptions and each line specifying LoadWith with a regular expression enclosed (something I don't know much about) identifying each child (related table) object to load.  Obvioiusly, depending on what data you wanted to load at the time you could include a limited number of children but in my case I wanted all relational data to be populated and sent to the WCF client for viewing/editing.
Hope this helps someone else out.

P.S. For what it's worth, I am using the PLINQO templates as mentioned earlier to setup, maintain and extend my LINQ entities and the dbml file and sp far I like it.  If you are interested in it you can do a Google search PLINQO and CodeSmith, the application that actually runs it.  One very nice feature, when you change your database schema you can actually refresh the dbml file and entities by regenerating the PLINQO output.  So far this has saved me a lot of time and it sets up a very clean project.

        Public Function GetCustomerVendor(ByVal ListID As Integer) As CommWrapper

            Dim Context As New DataContext

            Dim ret As New CommWrapper

            Dim dlOptions = New DataLoadOptions()

            ' Causes the Customer/Vendor to actively load the related data lists.  One required for each relational table.

            dlOptions.LoadWith(Of CustomersVendor)(Function(cv) cv.CustomerVendorAddressList)

            dlOptions.LoadWith(Of CustomersVendor)(Function(cv) cv.CustomerVendorCommissionList)

            dlOptions.LoadWith(Of CustomersVendor)(Function(cv) cv.CustomerVendorContactList)

            dlOptions.LoadWith(Of CustomersVendor)(Function(cv) cv.CustomerVendorEmailAddressList)

            dlOptions.LoadWith(Of CustomersVendor)(Function(cv) cv.CustomerVendorPhoneNumberList)

            Context.LoadOptions = dlOptions

            ret.CustomerVendorList = (From cv In Context.CustomersVendor _

                                  Where cv.ListID = ListID _

                                  Select cv).ToList

            Return ret

        End Function

Open in new window


Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…

948 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now