2

Background - I usually perform validation at a property level in the entity class itself, either using DataAnnotation attributes or by implementing the IValidatableObject interface. This code doesn't usually have access to a DBContext.

Then, I usually place more complex business rules validation in the Service layer. Examples of these sort of validations are: checking that a value is unique in the database, and checking other entity values. These classes do require a DBContext to query the database.

Issue - My problem is that I end up repeating the same code in the Service layer. For example, when I insert and update an entity, I repeat the same code for checking that the given value is unique.

I read about design patterns such as Constraint, Strategy, and Specification. I guess I just need a bit of help to put them together in a EF, layered context. Much appreciated.

3 Answers3

1

I would keep the validation at the entity level. Here you can check that the required properties are set, their values are correct and you can also compare properties on the entity as well. This ensures that the entity, regardless of other entities, is in a valid state.

In the Service layer you can validate any entities passed into the method by calling a Validate method and you can also compare to entities within the database.

In the instance of validating whether a ID is unique you could add a method on your repository called GetById whereby you pass in the ID of the entity you want to check and if it returns NULL, then you didn't find an entity with that ID therefore its unique.

For example:

public class MyRepository
{
  public MyEntity GetById(int id)
  {
    return _entitySet.FirstOrDefault( item => item.Id == id );
  }
}

public class MyService
{
  public void ServiceMethod(Entity entity)
  {
    if( _repository.GetById( entity.Id ) == null)
    {
      // entity.Id is unique!
    }
    else
    {
      // entity.Id is not unique!
    }
  }
}

Each of your repositories will have access to the entities is manages, such as an ObjectSet in Entity Framework (I think it's called that), so you can safely place any shared validation, in the context of a specific entity, on the repository.

For example:

public class MyRespository
{
    public bool IsIdUnique(int id)
    {
      Entity entity = _entitySet.FirstOrDefault( item => item.Id == id );
      return entity == null ? true : false;
    }
}

public class MyService
{
  public void ServiceMethod(Entity entity)
  {
    if( _repository.IsIdUnqiue(entity.Id) )
    {
      // entity.Id is unique!
    }
    else
    {
      // entity.Id is not unique!
    }
  }
}

You can also add the GetById to the MyService class above and have the IsIdUnique method call that rather than retype the lambda. This way you can reuse the GetById logic.

MotoSV
  • 2,348
  • 17
  • 27
1

When you have to go to the database then you need to use DbContext and DbContext has an Overridable method called ValidateEntity. See this article: Entity Framework Validation.

I put the code I use in another answer here

Community
  • 1
  • 1
Colin
  • 22,328
  • 17
  • 103
  • 197
0

Thank you for your answers, they were extremely insightful. I think this article answers my question properly. Much appreciated.

http://msdn.microsoft.com/en-us/data/gg193959.aspx