Look around the web. You will find no Update method in the repository patterns for entity framework implementations published. There are different flavors of retrieves, mark for insertions an deletions but no update implementation. And curiously this is the most painful. There are 2 options that you have. But to explain both, I will start off with the repository design. We can get into a discussion about the pattern in case anyone is interested, all you have to do is instigate me by posting a comment.

So now your IRepository here has some generic functions :
---
IEnumerable<T> All();
IEnumerable<T> FindAll(Func<T, bool> exp);
T Single(Func<T, bool> exp);
T First(Func<T, bool> exp);
void MarkForDeletion(T entity);
T CreateInstance();
void SaveAll();
---
These generic functions, if you notice, does not contain an update function. Now the 2 options that you have that I have talked about, are
Option 1: Do not take care of your updates in the provider. Now this is simple. Do all the updates in the logical layer that calls the data provider. Something like
---
Events dbEvent = null;
IEnumerable<Events> dbEvents = this.DataProvider.All<Events>(eve => eve.EventID.Equals(communityEvent.EventID));
if (dbEvents != null && dbEvents.Count() == 1)
{
dbEvent = dbEvents.SingleOrDefault();
}
else
{
throw new ApplicationException(MADConstants.GENERIC_DATA_ERROR);
}
dbEvent.DateModified = communityEvent.DateModified;
dbEvent.Description = communityEvent.Description;
dbEvent.EventEndDate = communityEvent.EventEndDate;
dbEvent.EventName = communityEvent.EventName;
dbEvent.EventStartDate = communityEvent.EventStartDate;
dbEvent.IsApproved = communityEvent.IsApproved;
dbEvent.LastModifiedBy = communityEvent.LastModifiedBy;
dbEvent.NoOfRatings = communityEvent.NoOfRatings;
dbEvent.Organizer = communityEvent.Organizer;
dbEvent.ParticipatedBy = communityEvent.ParticipatedBy;
dbEvent.RatedBy = communityEvent.RatedBy;
dbEvent.Rating = communityEvent.Rating;
dbEvent.Sessions = communityEvent.Sessions;
this.DataProvider.SaveAllChanges();
---
The second option which i feel is most elegant is this:
---
/// <summary>
/// Updates
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entityName"></param>
/// <param name="entity"></param>
public void Update<T>(string entityName, T entity)
{
this.context.AttachTo(entityName, entity);
}
---
So all you have to do now is to call the functions like this
---
DataProvider.Update<Customer>(“Customer”, customer);
DataProvider.SaveAllchanges();
---
The third option is a little complex. Please refer to the diagram above, the task repositories that you will implement must contain the update function like this:
public void Update(Customer customer)
{
context.Attach(customer); //Custom extensor method
context.SaveChanges();
}
This means you have all your Task Repositories that know the type of your entity. So a CustomerRepository would know that it is handling Customer Types and hence will take Customer as a parameter to the Update Method. This is because Attach method requires an argument that is of type System.Data.Objects.DataClasses.IEntityWithKey. Which means it will not accept type T because this does not have the entity key or the primary key on the basis of which it will know which entity / row to update in the database.
The purpose of the third option is that all interaction with the database that is specific to a particular entity can be handled in the Task Repositories.
We decided to implement the repository pattern for the Entity Framework Implementation in our project. So last couple of weeks people have been asking me why the repository pattern is required. I mean what is it that this pattern does besides giving a layer of abstraction, and providing the CRUD methods, which are also available in C# as a language feature (LINQ).
The answer is given aptly by Martin Fowler as, “A system with a complex domain model often benefits from a layer, such as the one provided by Data Mapper (165), that isolates domain objects from details of the database access code. In such systems it can be worthwhile to build another layer of abstraction over the mapping layer where query construction code is concentrated. This becomes more important when there are a large number of domain classes or heavy querying. In these cases particularly, adding this layer helps minimize duplicate query logic.
A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.”
This has a no. of benefits. Simplifying complexity, removing redundant querying, making code more testable, etc. Let’s say you want to test your code without going into the database and destroying it completely. unless you use DBUnit, This pattern helps you a lot. All you need to do is change your SaveChanges() function from
---
/// <summary>
/// Saves all changes in the current context.
/// </summary>
public virtual int SaveAllChanges()
{
try
{
((ObjectContext)this.Context).SaveChanges();
return 0;
}
catch
{
return -1;
}
}
---
to
---
/// <summary>
/// Saves all changes in the current context.
/// </summary>
public virtual int SaveAllChanges()
{
return 0;
}
---
On doing this, your changes are not populated to the database and you can do all your testing in-memory. Now is it a good idea to change your code to just make it testable? Well that’s a good question that needs discussing at length. Maybe in another post…