Kirk Evans Blog

.NET From a Markup Perspective

WCF and LINQ

@kaevans

WCF and LINQ

  • Comments 5

Jim Wooley posted an article about how to decorate LINQ datatypes with DataContractAttribute and DataMemberAttribute so that they can be serialized by WCF.  Sadly, this approach doesn't work anymore with Visual Studio 2008 Beta 2 and the LINQ to SQL classes designer since the custom attributes property Jim demonstrates is removed in Beta 2.

After banging my head against the keyboard for awhile, I fired off an email to the LINQ team and asked if it is possible to return LINQ classes from WCF services.  It is possible, it just sucks.  You need to click on the designer surface in your .dbml file and change the Serialization property to "Unidirectional". That will decorate the generated classes with DataContract and DataMember attributes appropriately. 

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

public class Service : IService
{
    public IEnumerable<TroubleTicket> GetTroubleTickets(Ani tn)
    {
        TroubleTicketsDataContext db = new TroubleTicketsDataContext(@"Server=(local);Integrated Security=true;Initial Catalog=tickets");
        var tickets = from t in db.GetTroubleTickets(tn.NPA, tn.NXX, tn.Line)                      
                      select  t;
        return tickets;   
    }
}

You can do this from command line as well.  There is a /serialization switch for sqlmetal.exe that will let you specify a value of "unidirectional".

This sucks.  The custom attributes approach is better because you can control the output, and is much simpler than diving into some funky XML mapping file to influence the serialization.  Since that feature has been removed, you are S.O.L. if you want to do things like remove a type from the serialization output or change its serialized name.  If you need any type of control over the serialization format, it seems better to just create the contracts and data transfer objects by hand, and programmatically map from one type to another:

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

public class Service : IService
{
    public IEnumerable<TroubleTicket> GetTroubleTickets(Ani tn)
    {
        TroubleTicketsDataContext db = new TroubleTicketsDataContext(@"Server=(local);Integrated Security=true;Initial Catalog=tickets");
        var tickets = from t in db.GetTroubleTickets(tn.NPA, tn.NXX, tn.Line)                      
                      select  t;
        List<Ticket> returnTickets = new List<Ticket>();
        foreach (var t in tickets)
        {
            returnTickets.Add(new Ticket{ID=t.TicketID,Description=t.Description};
        }
        return returnTickets;   
    }    
}

[DataContract]
public class Ticket
{
    [DataMember] public Guid ID { get; set; }
    [DataMember] public string Description { get; set; }
    [DataMember] public string NPA { get; set; }
    [DataMember] public string NXX { get; set; }
    [DataMember] public string Line { get; set; }
}

Looks like a great opportunity for a VSIP partner to step up and provide some excellent tooling for creating services with WCF and LINQ.

  • Kirk, You are right that this functionality was removed in Beta 2. It wouldn't take much to get the functionality back, just restore the ability to add custom attribtes from the designer or directly in the DBML fie. I have been meaning to update that post for some time now.

    If you didn't need to specify property custom DataMember mappings, you could just decorate the business portion of the partial class with the <Serializable> attribute, otherwise you are stuck with managing this manually as you pointed out. The portions in the original post regarding the CRUD functions is still valid.

  • It's actually pretty easy to write a system that copies one object to another based on compatible property types. In less than 100 lines, you can have an efficient (as efficient as a delegate invocation), customizable, object copier.

    But, yea, the LINQ to SQL object generator should let us have a tiny bit more control over things...

  • @Jim - thanks for the original post... great job, looking forward to the book!

    @Michael - I don't disagree, you could write one, but the point is that you don't need to invest the effort in building one in this case if the custom attributes functionality were just put back into Visual Studio 2008.  I can think of a number of other scenarios where I would want to decorate the generated types with attributes so that I could perform other processing on them as well.  

  • In my previous post, I showed how to use the DataContractSerializer with the classes generated by the

  • Oh definately; we should have control. I wasn't trying to imply that it wasn't a big deal :).

Page 1 of 1 (5 items)
Leave a Comment
  • Please add 7 and 5 and type the answer here:
  • Post
Translate This Page
Search
Archive
Archives