HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Entity Framework, code-first repository pattern review. Where to validate?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
validatewherefirstrepositorycodeframeworkreviewpatternentity

Problem

I've been iterating on my repository pattern implementation over the course of the past 4-5 months. In my new projects I choose to use this pattern and I try to improve upon what I learned in previous projects. I'm pretty pleased with the state of my current implementation. I feel like I could improve upon my validation logic somehow, though.

First and foremost, my code is on GitHub in its entirety: https://github.com/ryancole/Warcraft

Description of my implementation

I've gone with a layered approach consisting of my POCO entity classes, the repositories and finally services on top of the repositories. I have a service layer because I've chosen to use a generic repository class. My repository class is basic and provides the core CRUD operations. It's also purposefully leaky, because it's intended to sit behind my service layer - so, my repository class returns IQueryable. My service layer returns ICollection, on the other hand.

public interface IRepository where T : class
{
    #region Properties

    /// 
    /// Retrieve all entities
    /// 
    IQueryable All { get; }

    #endregion

    #region Methods

    /// 
    /// Count entities matching a predicate
    /// 
    int Count(Expression> predicate);

    /// 
    /// Insert an entity
    /// 
    T Insert(T entity);

    /// 
    /// Retrieve entities matching a predicate
    /// 
    IQueryable Where(Expression> predicate);

    #endregion
}


I have a unit of work class, which contains my DbContext instance and provides access to my various services. The unit of work class also exposes a SaveChanges method. The intention is that users of my libraries will just pass this unit of work class through to their MVC controllers, and therefor do not have to deal with any of the underlying contexts, repositories, etc - only the services with their explicitly crafted methods for specific tasks.

```
public interface ISession : IDisposable
{
#region Properties

IAccountService Accounts { g

Solution

The only thing that I think if slightly leaky is updating an existing entity.

It isn't the only leak you have:

public interface ISession : IDisposable


This is a leaky abstraction. You have a specific implementation in mind - one that implements IDisposable, and you're leaking this specific implementation into the ISession interface.

That said, I don't really see what the abstract repository earns you. I've seen people wrap EF with a repository/unit-of-work so that they could "swap the ORM" as needed (if that's ever needed), and I can understand why someone really willing to decouple their service layer from the underlying data access technology would want to do that.

But you're purposely leaking IQueryable into your service layer, which defeats the purpose of the repository abstraction.

Why bother? The added complexity doesn't seem to simplify extending the application. I think your service layer can afford to play with EF directly - DbContext is a repository and a unit-of-work. No need to look further.

What you've identified as a leak with the updating of entities, stems from the fact that your service layer is passing entities to your Web/UI layer - you need a seam here: entities belong with EF and the data-related stuff, not in your UI.

I have to admit I don't do much Web development, but in WPF I'd make that service layer work with ViewModel objects, and be able to "translate" a ViewModel into one or more entities. This "seam" completely decouples your front-end from your back-end. Yes, often the ViewModel class will look very similar to the entity class it's wrapping (see this question for a WPF example), but it will only expose what the UI is interested in, so you can keep fields like Id, DateInserted and DateUpdated in the service and data layers and not be bothered with them in the UI layer. I don't think that concern is WPF-specific.

With the service layer performing the "translation" between ViewModel and entity types, you have a perfectly logical spot to perform your validations in, exactly where you wanted to do them in the first place.

Code Snippets

public interface ISession : IDisposable

Context

StackExchange Code Review Q#39927, answer score: 5

Revisions (0)

No revisions yet.