In an n-tier application, is it possible to send objects created by LINQ between layers? More specifically, is it possible to send LINQ object via a WCF service?
Well, the short answer is yes. I will first show you how to do it then I will try and discuss why I want to do it and try and list the pros and cons!
I am only going to demo how to do this using the designer interface (LINQ to SQL - DBML) but it is also possible to use it in SQLMetal.exe!
I opened an existing project, clicked on the design surface and opened the properties window. Change the Serialization mode to Unidirectional

This basically indicates that id/idrefs are not to be used and thus make the objects serializable!
Now this object can be passed to and from a standard WCF service.
[ServiceContract]
public interface IContractService
{
[OperationContract]
Impilo.DataAccess.LinqToSQL.Contact GetContact(int ContactID);
[OperationContract]
Impilo.DataAccess.LinqToSQL.Address GetAddress(int AddressID);
}
OK, this all looks great, but what is the catch? Well, my first issue with this is that it looks like I might have circular references and this kind of breaks my serialization. Let me explain, if I have a Customer and Invoice object, then LINQ tries to make it easy to ask any customer for its invoices and to see who an invoice clients are. This creates a circular reference. Customer links to invoice who links back to customer. It is possible to specify in LINQ that I don't want this to happen, but this is an "out-of-the-box" feature!
The second issue had me bug checking for a while. When I started, I implemented my service as follows:
public Impilo.DataAccess.LinqToSQL.Address GetAddress(int AddressID)
{
Console.WriteLine("Request: Get Address for " + AddressID);
using (ImpiloDataContext dataContext = new ImpiloDataContext(".\\SQLEXPRESS"))
{
var ch = (from c in dataContext.Addresses
where c.AddressID == AddressID
select c).First();
return ch;
}
}
This all looked fine and it worked for the first Operation Contract but as soon as I implemented my second operation contract, I started getting errors. I can't explain this yet but here is my solution:
public class ContractService : IContractService
{
private ImpiloDataContext dataContext = new ImpiloDataContext(".\\SQLEXPRESS");
public Impilo.DataAccess.LinqToSQL.Address GetAddress(int AddressID)
{
Console.WriteLine("Request: Get Address for " + AddressID);
var ch = (from c in dataContext.Addresses
where c.AddressID == AddressID
select c).First();
return ch;
}
}
Next, let's discuss the WHY. Everybody would probably have different opinions about this but I will only discuss why I would want to do this. Please note that I am by no means an expert on n-tier applications and would love to hear your opinions about this. The first thing to note is that I only serialize the data contract and NEVER the data context (I don't even think it is possible to serialize it). Any other layer will then not be possible to do anything with this object in a way I have not intended it because it will always need the data context to do anything useful. I also believe that a LINQ object serialized is "cheaper" than coping from a LINQ object to a business entity. You lose a little flexibility in the fact that you are now tied to LINQ but for my specific need, I know I will only use MS SQL and LINQ.
The biggest plus of using this is that I get INotifyPropertyChanging and INotifyPropertyChanged for free! This simplifies binding.
Like I said earlier, I am no expert and would love to hear your opinions about this. Currently I don't think there are any best practices yet on how to use LINQ and WCF together...