Month: October 2009

Book review: Beginning ASP.NET MVC 1.0

A dear friend of mine, Simone Chiaretta, ASP.NET MVP wrote an interesting book about ASP.NET MVC in collaboration with Keyvan Nayyeri.

image

The book is Beginning ASP.NET MVC 1.0, edited by Wrox, available on Amazon.com at this address for the price of 31.49 USD.

I am going to write a review of this book because, first of all, I know Simone and his professionalism. Second, because I am working now on an ASP.NET MVC project in my company, and this book was really helpful for me, so I am pretty sure that it will be the same for you guys.

Summary and structure of the book.

The book has 19 chapters plus a couple of appendixes. Each chapter covers a specific argument. At the end of each chapter there is always a section for the exercises and a summary section. The first thing you will like about this book is the huge amount of sample code!

At the end of the book there is the appendix B that contains all the solutions related to each exercise, so you won’t get lost.

The appendix A has a lot of useful links that you can follow, resources, links, books and more.

Finally there is the index that is done for a “dev” reader. It’s not a normal index but an index divided by alphabetic order that includes also all those components and “code” that you will find in the book. So you will find, for example, the page that talks about “NHibernate”.

Case studies.

What I really liked about this book is the 2 case studies that you will find at the end. Simone has created these 2 case studies that will reflect 2 real solutions, one is a blog and the second one is … a surprise. I am not going to tell you everything because you must buy it. Wink

This is something really well done as you will apply all the knowledge you got through the book into 2 real solutions!

Chapters.

Of course I am not going to describe each chapter, but this is the list of chapters so you can understand why this book is so well done, IMHO:

  1. MVC pattern
  2. WebForm VS MVC
  3. Getting started
  4. The model
  5. The controller
  6. The view
  7. Routing
  8. Unite test concepts
  9. Testing ASP.NET MVC
  10. Components
  11. Action filters
  12. AJAX
  13. Deployment
  14. Leveraging ASP.NET WebForm futures
  15. Authentication and authorization
  16. Extend ASP.NET MVC
  17. Migrating from ASP.NET
  18. Case studies
  19. Resources
  20. Exercises solutions

Final Considerations.

I am a NET developer, most of time I develop Silverlight/WPF or WinForm applications. For fun I did a couple of ASP.NET MVC applications in the bank where I was working before, but my knowledge about ASP.NET MVC was relative to those projects.

Now that I got this book, I was able to read all the aspect of MVC pattern applied to ASP.NET and I feel comfortable to build a real application with this framework.

I did a real ASP.NET MVC application for the Company where I am working now, and I was able to do everything is less than 1 week, including the use of JQuery and AJAX.

I am really satisfied of this book and I hope that you will buy it as it is a very nice and well written book that will drive you inside this pretty cool framework.

Thanks Simone and Keyyvan for your effort!

Tags:

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

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: