Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

Sunday, October 25, 2009 11:05 AM | Leave a reply »

Update: source code and documentation are now available on CodePlex at this address: http://prismtutorial.codeplex.com/

Build a generic repository with the Entity Framework.

In the previous series of articles about M-V-VM we used the AdventureWorks database, available on CodePlex.
After this article (configure a data layer with LinQ-to-SQL) I have got some reader’s emails asking me this and that. So, I am going to give you all those answers right now.

Download and configure the Adventure Works database.

On my dev PC I have SQL Server 2008 Standard version, but this tutorial is working also with the express or any other version.

  1. Go to CodePlex Adventure Works web site project and download the AW available version (light and full). I have downloaded the package called ”Adventure Works All Databases”.
  2. Go into the folder tree Tools/Samples and you will find the .mdf and .ldf and also the T-SQL script if you want to run it from a prompt command line.
  3. Open your SSMS and from the master database, install the version that you prefer. My samples work with both version, as I use always the Adventure Works LT (Light version).

image

  1. Mandatory: as I use Windows Authentication in all my samples, you must fix that in your local Db and change the connection string in my samples.

Open Visual Studio and create the folder three.

As we are going to work with an enterprise application, in order to simulate the 3 tiers, I have created 3 solution folders, one for the data service, one for the client part and one for the test. We will expand these folders during the building process.

The initial solution three will be:

imageSolution name: PrismTutorial
DataLayer: PrismTutorial.DataLayer
  TDD: Test.DataLayer
Consuming Service: PrismTutorial.WCF

Working with Entity Framework.

In the first series of tutorials, we used LinQ-to-SQL because:

  • It’s easier, It’s faster, It uses the relation 1 to 1 with the database tables and so on.

For this tutorial we are going to use the Entity Framework because this one is the real OR/M coming from Microsoft so in an enterprise application it’s better to spend more time and effort on building something stronger and reusable.

Open you VS data layer solution, right click and add an new component, ADO.NET Entity Data Model and configure it to reflect the Adventure Works LT database installed into your machine.

After that VS will show up a entity model designer window very similar to the one that we used with Linq-to-SQL.

imageIf you want to be compliant with my settings, this is how I have configured my Entity Framework:

image

It’s time to play, the Entity Framework repository wrap!

Like any software architect, I try to fit always everything in a more generic, reusable and more readable pattern. If we want to have a reusable UnitOfWork associated with a Repository engine, we must wrap the Entity Framework inside something more generics. Here comes the pain ….

The final result I would like to have is this one:

image

IRepository interface.

First of all we have to define a generic contract (interface) that we will use as our repository. As we want to be generic we need something like this:

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq.Expressions;
  4: 
  5: namespace PrismTutorial.DataLayer {
  6:     public interface IRepository:IDisposable {
  7:         //Add a new Entity
  8:         int Add<T>(T entity);
  9:         //Count the number of entities available
 10:         long Count<T>();
 11:         //Count using a filer
 12:         long Count<T>(Expression<Func<T, bool>> expression);
 13:         //Delete an existing entity
 14:         int Delete<T>(T entity);
 15:         //List all the available entities
 16:         IList<T> GetAll<T>();
 17:         //List the entities using a filter
 18:         IList<T> GetAll<T>(Expression<Func<T, bool>> expression);
 19:         //Get a single entity
 20:         T GetSingle<T>(Expression<Func<T,bool>> expression);
 21:         //Update an existing entity
 22:         int Update<T>(T entity);
 23:     }
 24: }
 25: 

At this point we have a generic implementation of the repository pattern and we do not need to worry about what we are going to save, update or delete.

BaseRepository to handle the dispose of the data context.

The second problem that we have to fix is more related to how the entity framework uses the context in a web application. I have found this article over the web: http://blog.zoolutions.se/post/2009/03/26/Generic-Repository-for-Entity-Framework.aspx, really interesting, so I am going to use the same type of solution.

We need a simple base class that is going to handle the data context and close it if not needed. We can also use the using clause in each method of our repository. I want to use this solution just because it’s more clean and doesn’t force me to write too much code inside the final repository.

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5: 
  6: namespace PrismTutorial.DataLayer {
  7:     public abstract class BaseRepository {
  8:         //Our entity framework engine used in the solution
  9:         internal ADVConnection _context;
 10:         //Switch that tells us if the datacontext is reused
 11:         internal bool _contextReused;
 12:         
 13:         //This return the current, or a new connection through the EF
 14:         public ADVConnection GetObjectContext() {
 15:             if (!_contextReused) {
 16:                 return new ADVConnection();
 17:             }
 18:             return _context;
 19:         }
 20: 
 21:         //This is the public method that we will call from our repository
 22:         public void ReleaseObjectContextIfNotReused() {
 23:             if (!_contextReused) {
 24:                 ReleaseObjectContext();
 25:             }
 26:         }
 27: 
 28:         //Simple dispose of the current EF
 29:         public void ReleaseObjectContext() {
 30:             if (_context != null) {
 31:                 _context.Dispose();
 32:             }
 33:             _contextReused = false;
 34:         }
 35:     }
 36: }

Cool, we just need now to wrap all together and play with the data.

The concrete repository.

For the repository pattern there are two implementations, one is to keep everything generic and have 1 repository for the entire domain. The second one is to have a repository for each entity, like UserRepository, ProductRepository, and implement the CRUD operations related to the entity, like AddUser, AddProduct and so on.

I would suggest the second solution only if you need to include some business logic in your CRUD operations or there are some special development requirements. So let’s go for the easier and faster solution, he first one.

In the constructor of our repository we need to pass an instance of the UnitOfWork that in our case is the Entity Framework, like we do with the session with NHibernate.

  1: namespace PrismTutorial.DataLayer {
  2:     public class Repository:BaseRepository,IRepository {
  3: 
  4:         #region Base Implementation
  5: 
  6:         private bool _disposed;
  7:         //Here we pass the connection and we flag the contextReused
  8:         //so we can use the repository with the using clause ...
  9:         public Repository(ADVConnection context) {
 10:             this._context = context;
 11:             this._contextReused = true;
 12:         }
 13: 
 14:         #endregion

Then we have also to implement the IDisposable interface in order to clean-up the connection after each call:

  1:         #region Disposable
  2:         //Dispose implementation
  3:         public void Dispose() {
  4:             DisposeObject(true);
  5:             GC.SuppressFinalize(this);
  6:         }
  7:         //Distructor
  8:         ~Repository() {
  9:             DisposeObject(false);
 10:         }
 11:         //Concrete private implementation of the dispose method
 12:         private void DisposeObject(bool disposing) {
 13:             if (_disposed) {
 14:                 return;
 15:             }
 16:             if (disposing) {
 17:                 if (_context != null) {
 18:                     _context.Dispose();
 19:                 }
 20:                 _disposed = true;
 21:             }
 22:         }
 23:         #endregion

Now we can go ahead and implement each C.R.U.D. method and reflects the changes in the entity framework.

The save method is pretty straightforward, we add an object to our context, using it’s FullTypeName and we persist the changes in the database.

  1:         public int Add<T>(T entity) {
  2:             ADVConnection context = GetObjectContext();
  3:             context.AddObject(typeof(T).Name, entity);
  4:             int result = context.SaveChanges();
  5:             ReleaseObjectContextIfNotReused();
  6:             return result;
  7:         }

Same for the count methods except that we have to create an ObjectQuery that it’s nothing more than a translated query using the T object passed as a parameter.

  1:         public long Count<T>() {
  2:             ADVConnection context = GetObjectContext();
  3:             var query = new ObjectQuery<T>(
  4:                 typeof(T).Name, 
  5:                 context, 
  6:                 MergeOption.NoTracking);
  7:             int count = query.Count();
  8:             ReleaseObjectContextIfNotReused();
  9:             return count;
 10:         }
 11: 
 12:         public long Count<T>(Expression<Func<T, bool>> expression) {
 13:             ADVConnection context = GetObjectContext();
 14:             var query = new ObjectQuery<T>(
 15:                 typeof(T).Name, 
 16:                 context, 
 17:                 MergeOption.NoTracking)
 18:                 .Where(expression);
 19:             int count = query.Count();
 20:             ReleaseObjectContextIfNotReused();
 21:             return count;
 22:         }
 23: 

The only part that you may not know is the parameter MergeOption used in the objectquery constructor. MergeOption has the following values (from the source of the NET Framework) :

  1: namespace System.Data.Objects {
  2:     // Summary:
  3:     //     Specifies how objects being loaded into the object context are merged with
  4:     //     objects already in the object context.
  5:     public enum MergeOption {
  6:         // Summary:
  7:         //     Objects that already exist in the object context are not loaded from the
  8:         //     persisted store. This is the default behavior for queries or when calling
  9:         //     the System.Data.Objects.DataClasses.EntityCollection<TEntity>.Load(System.Data.Objects.MergeOption)
 10:         //     method on an System.Data.Objects.DataClasses.EntityCollection<TEntity>.
 11:         AppendOnly = 0,
 12:         //
 13:         // Summary:
 14:         //     Objects are always loaded from the persisted store. Any property changes
 15:         //     made to objects in the object context are overwritten by the store values.
 16:         OverwriteChanges = 1,
 17:         //
 18:         // Summary:
 19:         //     When an object exists in the object context, it is not loaded from the persisted
 20:         //     store. Any property changes made to objects in the object context are preserved.
 21:         //     This is used to force changes to objects in the object context to save successfully
 22:         //     after an System.Data.OptimisticConcurrencyException has occurred. For more
 23:         //     information, see Saving Changes and Managing Concurrency (Entity Framework).
 24:         PreserveChanges = 2,
 25:         //
 26:         // Summary:
 27:         //     Objects are maintained in a System.Data.EntityState.Detached state and are
 28:         //     not tracked in the System.Data.Objects.ObjectStateManager.
 29:         NoTracking = 3,
 30:     }
 31: }
 32: 

Then we need to implement the delete command. Because we are working on a disconnected environment, first of all we need to get the original object from the repository. Then, we delete it.

  1: public int Delete<T>(T entity) {
  2:     ADVConnection context = GetObjectContext();
  3:     object originalItem;
  4:     EntityKey key = context.CreateEntityKey(typeof(T).Name, entity);
  5:     if(context.TryGetObjectByKey(key, out originalItem)){
  6:         context.DeleteObject(originalItem);
  7:     }
  8:     int result =  context.SaveChanges();
  9:     ReleaseObjectContextIfNotReused();
 10:     return result;
 11: }
 12: 

Now the easy part, GetAll and GetAll using an expression for the criteria.

  1: public IList<T> GetAll<T>() {
  2:     ADVConnection context = GetObjectContext();
  3:     IList<T> list = context
  4:         .CreateQuery<T>(
  5:         "[" + typeof(T).Name + "]")
  6:         .ToList();
  7:     ReleaseObjectContextIfNotReused();
  8:     return list;
  9: }
 10: 

With the criteria:

  1: public IList<T> GetAll<T>(Expression<Func<T, bool>> expression) {
  2:     ADVConnection context = GetObjectContext();
  3:     IList<T> list = context
  4:         .CreateQuery<T>(
  5:         "[" + typeof(T).Name + "]")
  6:         .Where(expression)
  7:         .ToList();
  8:     ReleaseObjectContextIfNotReused();
  9:     return list;
 10: }
 11: 
Just a little note here. If you watch this piece of code:

.CreateQuery<T>(
                "[" + typeof(T).Name + "]")
here I am using the CreateQuery method to get an ObjectQuery object using the generics. Unfortunately this method requires the name of the entity, so we use Reflection and get the name with the method typeof.

The GetSingle method is the same, we just retreive the FirstOrDefault result of our query:

  1: public T GetSingle<T>(Expression<Func<T, bool>> expression) {
  2:     ADVConnection context = GetObjectContext();
  3:     T result = context
  4:         .CreateQuery<T>(
  5:         "[" + typeof(T).Name + "]")
  6:         .Where(expression)
  7:         .FirstOrDefault();
  8:     ReleaseObjectContextIfNotReused();
  9:     return result;
 10: }
 11: 

And finally, the update method that is going to save the changes we did to an entity.

  1: public int Update<T>(T entity) {
  2:     ADVConnection context = GetObjectContext();
  3:     object originalItem;
  4:     EntityKey key = context.CreateEntityKey(typeof(T).Name, entity);
  5:     if(context.TryGetObjectByKey(key, out originalItem)){
  6:         context.ApplyPropertyChanges(typeof(T).Name,entity);
  7:     }
  8:     int result = context.SaveChanges();
  9:     ReleaseObjectContextIfNotReused();
 10:     return result;
 11: }
 12: 

Like we did with the delete method, first of all we need to retrieve the original instance of the entity, then we simply apply the changes we got from the “working” entity, using the method ApplyPropertyChanges and finally we save everything.

Conclusions.

In this article we saw how to work with the entity framework and build a repository pattern around it. The next step will be to include business and value validation to our entities. We will use the enterprise library 4.1.

Stay tuned!

Tags:


Comments

  1. Gravatar Jose says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    Great article.
    Would you publish the source code?
  2. Gravatar raffaeu says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    Yes starting from the next week, like I did for the MVVM series, the tutorial will have a reference project on CodePlex.
    Stay tuned!
  3. Re : # Social comments and analytics for this post

    This post was mentioned on Twitter by SolidsoftLtd: Build enterprise application with WPF, WCF, Entity Framework and ...: This is the blog of Raffaeu (Raffael.. http://bit.ly/2y19Ug
    #WCF
  4. Gravatar alin says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    One question: why use enterprise library 4.1 ?
    Looking forward for the new tutorial
  5. Gravatar raffaeu says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    Alin I use Enterprise Library for those reasons:
    1- Rich documentations and samples over the network
    2- A huge codeplex project with a lot of users
    3- complete application block (UI, cache, log, IoC, Validation) all in one framework
  6. Gravatar creatin says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    One of the key advantages to the Windows Presentation Foundation is that it provides a consistent model of programming for making applications, and it clearly delineates between the business logic and the user interface.
  7. Gravatar Sys says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    Great tutorial!
    After reading i'm wondering how i should implement the crud operations for many-to-many relationed entities eg. customer, customer_address, address where customer doesn't have a direct reference to address but to customer_address only.
  8. Gravatar raffaeu says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    We will see these and other issues in the next articles. I have been busy on a project in the office but I am planning to write some nice articles in the next week, stay tuned!
  9. Gravatar Luca says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    Great post Raffaele...interesting and inspiring the way you create the repository of the UoW around EF.
    I'm just starting the development of an application using WPF, WF, WCF and PRISM, but all with the new .NET 4.0 and VisualStudio 2010...I'm just wondering whether with the new EF 4.0 I need to implement the UoW and the Repository or not...I know it's a pattern and so not bound to any technology...but what' your opinion ?
  10. Gravatar raffaeu says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    Well everything depends always on what you have to do and how much complex is the project.
    Of course if you will be the only developer and you won't have time to play around with generics and a query object, you should consider to use directly EF.
    I use the repository pattern because I don't use LinQ directly but I work with my query model that is able to translate LinQ or HQL in a unique standard query model.
    Honestly with EF or LinQ, the UnitOfWork should not be used because they have the DataContext that is already a UoW.
    In this series, it's mandatory that I explain all the available patterns and solutions to build an enterprise app.
  11. Gravatar Luca says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    yep...you're right...I've missed this, EF and Linq to Sql have a datacontext that itself is a UoW...

    The project itself is a porting of a Windows Form .NET 3.5 project and we decided to do this to get the advantage of the new WF 4.0(engine, designer...a lot of beatiful changes in it)...

    I think I'll use EF 4.0 because I love POCO entities and it seems EF support them and I want to eliminate the need to use a DTO layer with the "automapper" stuffs inside...

    Hope to post somethings about it....

    PS. just subscribed to your blog feed, so I won't miss your future post...

  12. Gravatar Kamel says:

    Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    thank you for this article.

    in the last section at the update method i found that the following method is deprecated

    context.ApplyPropertyChanges(typeofT).Name,entity);



    what is the alternative one and how can i use it.

    thanks again.
  13. Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    Great post, thank you!
    I just don't get one thing: why did you need to implement a finalizer in your Repository class. I don't see any unmanaged resources used by Repository. Seems to me it's totally useless.
  14. Re : # re: Build enterprise application with WPF, WCF, Entity Framework and Prism. Tutorial 02.

    Hi, The images in the posts are not displaying. Looks like the links are broken. Please check
Comments have been closed on this topic.