Sometimes we need to pass a simple data object through WCF service. There are a few simple steps to performing this task.
Make data objects declare columns as Data Members
This step is very simple: all that’s needed is to define in the DBML editor that the serialization mode is Unidirectional.
By defining this serialization mode the generated code will be decorated with DataContract and DataMember attributes on classes and columns. By doing so the objects are compatible with WCF service and declared as part of the contract.
Visit the objects associations properties before returning them from the service
For example, if we’re dealing with this simple schema and our service returns a customer with requested ID.
Assuming we have this naive code:
public class StoreService : IStoreService
{
public Customer GetCustomer(int id)
{
using (var store = new StoreDataContext())
{
return store.Customers.First(dbCustomer => dbCustomer.ID == id);
}
}
}
The client will get the correct customer, but it won’t have the Orders property filled, even if the customer has orders the property value will be null. The reason for this behavior is that the generated code doesn’t execute the query against the database when it’s serializing. The solution is to access all data members before it serializes.
public class StoreService : IStoreService
{
public Customer GetCustomerWithRelations(int id)
{
using (var store = new StoreDataContext())
{
Customer customer = store.Customers.First(dbCustomer => dbCustomer.ID == id);
VisitDataMembers(customer);
return customer;
}
}
public static void VisitDataMembers(object dataMember)
{
if (dataMember == null)
{
return;
}
bool isEnumerable = dataMember is IEnumerable;
if (isEnumerable)
{
foreach (var item in (IEnumerable)dataMember)
{
VisitDataMembers(item);
}
}
var properties = dataMember.GetType().GetProperties();
IEnumerable<PropertyInfo> dataMemberProperties =
properties.Where(property => property.IsDefined(typeof(DataMemberAttribute), true));
foreach (PropertyInfo dataMemberProperty in dataMemberProperties)
{
var dataMemberValue = dataMemberProperty.GetValue(dataMember, null);
VisitDataMembers(dataMemberValue);
}
}
}
This VisitDataMembers method ensures all data members’ properties are accessed at least once before serialization and the client will be able to use all the data which is accessible for the data object tree. For example in the sample schema, the client will be able to get from customer to orders to products to materials.