One of the projects that my team is working on is a major WCF service that will serve as a hub for our company-specific data. This hub will allow multiple other projects to query for and receive certain data. Because we want to use Entity Framework for the data-access layer and WCF for the service layer, we figured we could just use the created Entity Framework Code First classes as DataContracts over WCF.

Something like this:

[Table("Team")]
[DataContract]
public class Team
{
    [DataMember]
    [Key]
    public int Id { get; set; }

    [DataMember]
    [Required]
    [StringLength(500)]
    public string Name { get; set; }
    
    ...

    [DataMember]
    public virtual ICollection<Player> Players { get; set; }
}

Anybody who has tried this before, though, will immediately tell you that this is a horrible idea, for the simple reason that Entity Framework Entities have trouble serializing (specifically Navigation Properties have all kinds of issues with serialization), and WCF requires any DataContracts to be serializable.  So what were we to do?

We were to use Data Transfer Objects (DTOs).

Data Transfer Objects

DTOs are exactly what they sound like: a construct designed to pass data from one system to another, nothing more and nothing less. In general, DTOs should contain only data and not business logic; it is up to the supplying and receiving systems to determine what to do with the data a DTO carries. In our case, the DTOs ended up being our class that we use the [DataContract] attribute on.

So, our Entity Framework object might look like this:

[Table("Team")]
public class Team
{
    [Key]
    public int Id { get; set; }

    [Required]
    [StringLength(500)]
    public string Name { get; set; }

    public DateTime OrganizationDate { get; set; }
    
    ...

    public virtual ICollection<Player> Players { get; set; }
}

And our corresponding DTO would look like this:

[DataContract]
public class TeamDTO
{
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public DateTime FoundingDate { get; set; }
    
    ...

    [DataMember]
    public List<PlayerDTO> Players { get; set; }
}

Now we could simply use the TeamDTO and PlayerDTO classes to move data back and forth from our service to the client systems and vice versa. Voila!

Mapping Entities to DTOs with AutoMapper

Except, we weren't quite done. Now we'd end up with a ton of mapping code, like this:

public TeamDTO GetByID(int id)
{
    var team = ... //Get Team entity from data store
    var teamDto = new TeamDTO()
    {
        Id = team.Id,
        Name = team.Name,
        FoundingDate = team.OrganizationDate
        ...
    }
}

That sucks to write, it sucks to read, it sucks to maintain. There must be a better way, and there is: AutoMapper. AutoMapper is a conventions-based mapping system that allows you to copy values from an instance of one class to an instance of another class using pre-defined maps. Once we've got AutoMapper set up, the mapping code becomes super simple:

public TeamDTO GetByID(int id)
{
    var team = ... //Get Team entity from data store
    return Mapper.Map<TeamDTO>(team);
}

Now this is much easier to read.

Of course, with that kind of power comes some setup. We need to define the maps in advance. Often, my team will do this in a static AutoMapperConfiguration class:

public static class AutoMapperConfiguration
{
    public static void Configure() 
    {
        Mapper.CreateMap<Team, TeamDTO>();
    }
}

Then, we call that Configure() method from the Global.asax file (or elsewhere on application startup).

But how does it actually create that map? AutoMapper uses reflection to look at the properties of the source and destination classes (in the example above, the source class is the Team entity and the destination class is the TeamDTO data transfer object). For any property with the same name and type that occurs in both classes, a map definition is created that specifies that the value from an property of the source class should be moved to the value of a property of the destination class.

But what about the navigation properties that EF uses? Generally, we want to ignore those values, as mapping them could have unintended consequences (e.g. attempting to map navigation properties while still in the same context could end up loading a LOT of your database into memory). So, if we want to ignore a particular property in the source value, we could modify our AutoMapper map like so:

public static class AutoMapperConfiguration
{
    public static void Configure() 
    {
        Mapper.CreateMap<Team, TeamDTO>()
              .ForMember(dest => dest.Players, opt => opt.Ignore());
    }
}

If your names don't exactly match, you could use the MapFrom() method:

public static class AutoMapperConfiguration
{
    public static void Configure() 
    {
        Mapper.CreateMap<Team, TeamDTO>()
              .ForMember(dest => dest.Players, opt => opt.Ignore())
              .ForMember(dest => dest.FoundingDate, opt => opt.MapFrom(src => src.OrganizationDate));
    }
}

AutoMapper is hugely configurable and provides us a lot of power and brevity. That said, it's possible you'll encounter performance issues in high-performance apps, so as always, do some research yourself to determine if AutoMapper is right for your scenario.

Regardless of whether you use AutoMapper to map them, using DTOs has, in my opinion, consistently been proven to solve the gap between EF Entities and WCF DataContracts. It's really just another application of the Single Responsibility Principle: your classes should only do one thing.

Anybody out there using another solution (rather than DTOs) to bind Entity Framework and WCF? I would love to hear what you're working on and how it's going. Let me know in the comments!

Happy Coding!