views:

123

answers:

3

Just need to clarify this one, If I have the below interface

public interface IRepository<T>
{
    T Add(T entity);
}

when implementing it, does checking for duplication if entity is already existing before persist it is still a job of the Repository, or it should handle some where else?

A: 

If the entity already exists, you can either throw an exception, or update the existing entity's fields.

If you choose the latter, the method should probably be called something like AddOrUpdate()

Linq to SQL example

If I am retrieving a single record, I will use

public Entity GetEntity(int entityID)
{
    return dataContext.Entities.SingleOrDefault(e => e.EntityID = entityID);
}

...And in the calling method, I will check to see if what is returned is null before attempting to use the returned entity.

If I am updating a record, I will retrieve the entity as shown, edit the entity, and then call an UpdateEntity(entityID) repository method to update the fields in the database.

If I am adding a record, it's even easier. Since this is a database, and my tables always contain an Identity field of type int (an auto-assignable number, essentially), adding a record is the simplest operation of all (it's always a new record):

Public void InsertEntity(Entity entity)
{
    dataContext.Entities.InsertOnSubmit(entity);
    dataContext.SubmitChanges();
}

Business rules (email addresses are unique, for example) can be handled in the repository, or in a separate business layer. If you are looking for the most "correct" way, I think most people would agree that business rules belong in their own Business Logic Layer.

Robert Harvey
That's exactly my question. is checking if entity is existing (if exists, throw an exception otherwise AddOrUpdate) is a job of the repository?
No Body
See my edit....
Robert Harvey
No Body
Ah, yes, I figured you'd say something like that. Business rules (which is what you described) can be executed either in the repository, or in a separate business logic layer if you need an additional layer of indirection.
Robert Harvey
@No Body, if you have a couple of unique fields that aren't the primary key, then you will need to do some checking at another point. As Rob Harvey mentions, you can do it in the Repository, blocking the the `Add()` or before that, so that the `Add()` doesn't get called in the first place. I have some code that does this on another computer, I will post that asap.
Alastair Pitts
@Alastair Pitts, so does it means checking for unique fields is also part of the job of repository?
No Body
@No Body, yes. As you are interracting with the database it should definately be part of the Repository. I have a method on my UserRepository called IsUniqueEmailAddress().
Alastair Pitts
A: 

Yes - I recommend doing these checks in the repository.

Long answer: The term "repository" is a bit vague, but it is used more and more as the name of the persistence abstraction layer. The name is nice, but does not say too much: If you take Asp.Net MVC as an example, the sample apps, like Neirds dinner and alike, or codeplex projects encapsulate data access by the repository class. If such layer is implemented with a relational database for instancce, the primary keys of the tables will not allow duplicate entries, which means that in this case the repository implementation will throw an exception if 2 entries with the same key are inserted. So in other words, a RDBMS-implementation of a repository will quite always due this check, you wont be able to avoid it. So to make the behavior of repostories out there in the world most similar and to avoid surprises, lets all of them do this check.

It is a second question whether you should maintain in the business logic already that your Add() method is not alled with an entry that already exists. Sometimes it makes good sense to resolve this only at a single point, the database for instance, due to concurrency issues or savings of roundtrips. On the other hand it is for instance nice to tell the user as soon as possible that a username is already taken. So this depends.

have a nice day

A: 

Essentially the decision on where to handle that case depends on your exact requirements.

If you have business rules that define clear cut actions for when this happens, eg if a duplicate exists the new item should be renamed, then it can be built into the repository class.

On the other hand, if more complex rules are in place whereby, for example, more information is required to change the item before adding, then it should be handled further up the food chain.

The concept of a repository states that it exists to perform the persistence activities. So if you can do it all within the repository, that's fine. If you find you start to reference outside the repository, or your repository has dependencies, eg calling another repository, or a service, or a manager (or whatever processor nomenclature you prefer), then it's a good sign to take it back a step.

krisg