Click here to Skip to main content
13,831,643 members
Click here to Skip to main content
Add your own
alternative version


174 bookmarked
Posted 28 Jun 2010
Licenced CPOL

WCF by Example - Chapter I - Baseline

, 19 Dec 2012
Rate this:
Please Sign up or sign in to vote.
First draft version of the model, repository, and services.
IntroductionChapter II

The Series

WCF by example is a series of articles that describe how to design and develop a WPF client using WCF for communication and NHibernate for persistence purposes. The series introduction describes the scope of the articles and the project.

Chapter Overview

This is the first chapter of the series. This chapter sets the baseline for the eDirectory solution; we will introduce some core solution concepts as the Customer entity, the definition of the repository, a customer service, and our first couple tests. In later chapters we discuss how to evolve the original design described in this articles and how we can streamline the persistence components so when additional new entities are required, there is very little effort in getting this side of the solution working. 

The latest code for the eDirectory solution is found at CodePlex.

The Model - Customer Entity

As we mentioned in our introduction, we will keep our model very simple, only one entity for the moment will be required. The customer class is declared as:

public class Customer
    protected Customer() { }

    public long Id { get; private set; }
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public string Telephone { get; private set; }

Couple things to observe; properties are protected so they can only be changed by action methods; the class does not provide a public constructor, in this way we strive in setting up classes where their state can only be changed by using well known methods declared within the entity. We should not assume that our classes are going to be used in the proper way so making the constructor protected provides a nice way to control the creation of new instances. We will justify this approach when we cover persistence in a Chapter II - Repositories

Also, entities are defined in the eDirectory.Domain assembly which will be used only by our server side components; however, the client does not use the domain classes, instead DTOs are provided to the client. 

The Customer Services

The eDirectory provides the following customer services:

Function Description
GetById Retrieves a customer by providing a unique ID
ListAll Returns all customer instances
CreateNewCustomer Creates a new customer instance
UpdateCustomer Amends an existing customer instance

Services are defined using the following conventions:

  • Input parameters will be primitives or data transfer objects
  • All the service methods are functions, that is, they all return some minimal information back to the client.
We must keep our service signatures simple so WCF serialization problems are avoided. We also want to provide a communication pattern between the client and server without relying on a specific WCF mechanism, we will see in Chapter III - Response how this aspect is resolved. 

Also, service contracts (interfaces) are declared in a common assembly as both the server and client components require them, we will not use the Web References wizard feature in the client side to generate WCF proxies in the client side. The same is true for the DTOs where they are shared across both the server and client components. 

At this stage, we need our first DTO which looks very similar to our Customer entity: 

public class CustomerDto
    public long CustomerId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Telephone { get; set; }

Now, we can define our first service contract:

[ServiceContract(Namespace = "http://wcfbyexample/customerservices/")]
public interface ICustomerService
    CustomerDto CreateNewCustomer(CustomerDto customer);

    CustomerDto GetById(long id);

    CustomerDto UpdateCustomer(CustomerDto customer);

    List<customerdto> FindAll();

Let's try to create a mechanism for creating customer instances.


Domain entities should be decoupled from the persistence back-end mechanism. The repository pattern provides the required persistence functionality to our domain entities fulfilling the decoupling aspect.

At this point, the following repository definition is sufficient:

public interface IRepository<TEntity>
    #region CRUD operations
    TEntity Save(TEntity instance);
    void Update(TEntity instance);
    void Remove(TEntity instance);

    #region Retrieval Operations

    TEntity GetById(long id);
    IQueryable<TEntity> FindAll();

The most important aspects to notice are that we have defined a generic repository and that the FindAll method returns an IQueryable instance.

Create Factory Method

At this point, we can go back to our domain class and provide a mechanism to facilitate the creation of customer instances: 

public static Customer Create(IRepository<customer> repository, CustomerDto operation)
    var instance = new Customer
                                FirstName = operation.FirstName,
                                LastName = operation.LastName,
                                Telephone = operation.Telephone

    return instance;

See how the DTO instance is used to populate the properties of a new customer instance. Then the save method is executed against the passed repository. Instead of using a reference to the repository implementation in our entities, we will pass an instance of the repository to our entity methods and factories. This approach will evolve as we cover future aspects of the application. Another aspect to notice here is that the factory method creates persisted customer instances, so when the customer instance is returned, the persistence context is fully aware of the new instance, in fact the Id is available after the save method is invoked.

In-Memory Repository Implementation

At this point, we could start doing some TDD, we could mock repositories and so on, but providing an in-memory repository implementation is relatively inexpensive and leverages testing and business exploration. As the In-Memory persistor will never be used in a production environment, we want to declare this implementation in a different assembly: eDirectory.Naive. We define an abstract class for in-memory persistors with the common functionality:

public abstract class RepositoryEntityStore<TEntity>
    protected readonly IDictionary<long, TEntity> RepositoryMap = new Dictionary<long, TEntity>();

    #region IRepository<TEntity> Members

    public abstract TEntity Save(TEntity instance);

    public abstract void Update(TEntity instance);

    public abstract void Remove(TEntity instance);

    public TEntity GetById(long id)
        return RepositoryMap[id];

    public IQueryable<TEntity> FindAll()
        return RepositoryMap.Values.AsQueryable();


Then we create the Customer implementation:

public class RepositoryCustomer
        : RepositoryEntityStore<customer>
    public override Customer Save(Customer instance)

    public override void Update(Customer instance)

    public override void Remove(Customer instance)

    private void GetNewId(Customer instance)

    private readonly IDictionary<type,> Setters = new Dictionary<type,>();

    private MethodInfo GetSetter(Type type)

There is plenty of room for improvement in the above code, but it is worth noting how the entities are stored in a hashed map using the entity ID. As I mentioned in the series introduction, we have full control over our database design so we have chosen to have a numeric primary key in all our tables which eases the domain entities definition. In the next later chapter: Chapter II - Repositories , we will see how the above code evolves and one single implementation for all entity types alone is only required. 

Our First Test

Let's create a customer using the factory and then we check that the ID and first name are correct:

public class CustomerTests
    public void CreateCustomer()
        // need to create an instance of the repository
        var repository = new RepositoryCustomer();
        var dto = new CustomerDto
                                        FirstName = "Joe",
                                        LastName = "Bloggs",
                                        Telephone = "9999-8888"

        var customer = Customer.Create(repository, dto);
        Assert.IsFalse(customer.Id == 0, "Customer Id should have been updated");
        Assert.AreSame(customer.FirstName, dto.FirstName, "First Name are different");

Customer Service Implementation

We are now ready to create our first service implementation:

public class CustomerService
    public IRepository<customer> Repository { get; set; }
    #region ICustomerService Members

    public Common.Dto.Customer.CustomerDto CreateNewCustomer(CustomerDto dto)
        var customer = Customer.Create(Repository, dto);
        return new CustomerDto
                                CustomerId = customer.Id,
                                FirstName = customer.FirstName,
                                LastName = customer.LastName,
                                Telephone = customer.Telephone

Let's create a test that executes this service:

public class CustomerServiceTests
    public void CreateCustomer()
        // need to create an instance of the repository
        var service = new CustomerService { Repository = new RepositoryCustomer() };
        var dto = new CustomerDto
                                FirstName = "Joe",
                                LastName = "Bloggs",
                                Telephone = "9999-8888"

        var customer = service.CreateNewCustomer(dto);
        Assert.IsFalse(customer.CustomerId == 0, 
            "Customer Id should have been updated");
        Assert.AreSame(customer.FirstName, dto.FirstName, 
                       "First Name are different");

Chapter Conclusion

We have covered a lot of aspects in this article. In the first place, we set up a few projects: Common, Domain, and Naive. We described the basics about designing domain entities and their relation to the repository. We concluded the chapter using the service to create a customer instance and wrote our first couple tests.

In the next chapter, we will discuss some of the proposed patterns used so far, we will identify a few aspects that could be improved, and we will introduce the Repository Locator concept.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Enrique Albert
Software Developer (Senior)
Ireland Ireland
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionReplacing Entities with normal entity didn't work. Pin
Member 1114281624-Aug-15 8:58
memberMember 1114281624-Aug-15 8:58 
AnswerRe: Replacing Entities with normal entity didn't work. Pin
Enrique Albert7-Oct-15 2:19
memberEnrique Albert7-Oct-15 2:19 
GeneralMy vote of 5 Pin
goolz28-Jun-14 4:23
membergoolz28-Jun-14 4:23 
Questionclass RepositoryEntityStore<tentity> Pin
Member 34156439-Jul-12 22:54
memberMember 34156439-Jul-12 22:54 
GeneralRe: class RepositoryEntityStore Pin
Enrique Albert9-Jul-12 23:31
memberEnrique Albert9-Jul-12 23:31 
GeneralMy vote of 5 Pin
WestieBoy25-Jan-11 15:03
memberWestieBoy25-Jan-11 15:03 
Generalhave 5 Pin
Pranay Rana19-Dec-10 19:19
professionalPranay Rana19-Dec-10 19:19 
QuestionEntities referencing other Entities Pin
rittersh17-Sep-10 9:23
memberrittersh17-Sep-10 9:23 
AnswerRe: Entities referencing other Entities Pin
Enrique Albert18-Sep-10 3:49
memberEnrique Albert18-Sep-10 3:49 
GeneralRe: Entities referencing other Entities Pin
rittersh27-Sep-10 11:38
memberrittersh27-Sep-10 11:38 
GeneralRe: Entities referencing other Entities Pin
Enrique Albert27-Sep-10 17:43
memberEnrique Albert27-Sep-10 17:43 
AnswerRe: Entities referencing other Entities Pin
Enrique Albert14-Nov-10 3:25
memberEnrique Albert14-Nov-10 3:25 
QuestionHow do you run/deploy this application Pin
rittersh10-Sep-10 8:49
memberrittersh10-Sep-10 8:49 
AnswerRe: How do you run/deploy this application [modified] Pin
Enrique Albert12-Sep-10 5:44
memberEnrique Albert12-Sep-10 5:44 
AnswerRe: How do you run/deploy this application Pin
Enrique Albert12-Sep-10 6:04
memberEnrique Albert12-Sep-10 6:04 
GeneralMy vote of 5 Pin
defwebserver12-Jul-10 3:41
memberdefwebserver12-Jul-10 3:41 
GeneralRe: My vote of 5 Pin
Enrique Albert15-Sep-10 17:00
memberEnrique Albert15-Sep-10 17:00 
Generaljust a thought Pin
stefan popa6-Jul-10 9:01
memberstefan popa6-Jul-10 9:01 
GeneralRe: just a thought Pin
Enrique Albert6-Jul-10 16:25
memberEnrique Albert6-Jul-10 16:25 
Generalgood start Pin
kalyankrishna129-Jun-10 21:17
memberkalyankrishna129-Jun-10 21:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.190114.1 | Last Updated 19 Dec 2012
Article Copyright 2010 by Enrique Albert
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid