1

I am attempting to follow the repository pattern described here.

Can someone please shed some light on what this really means, and what the benefits of it are? The

<TEntity> where TEntity : class, IEntity

part of the classes signature

public interface IRepository<TEntity> where TEntity : class, IEntity
{
    TEntity Get(int id);

    int Save(TEntity entity);

    void Delete(TEntity entity);        
}

I do not see any noticeable effect in my implementation of IRepository:

public class AppUserRepository : Repository, IRepository<AppUser>
{
    public void Delete(AppUser entity)
    {
        using ( var context = new SourceEntities())
        {
            context.AppUsers.Attach(entity);
            context.AppUsers.Remove(entity);
            context.SaveChanges();
        }
    }

    public AppUser Get(int id)
    {
        using (var context = new SourceEntities())
        {
            return context.AppUsers.Where(x => x.Id == id).SingleOrDefault();
        }
    }

    public int Save(AppUser entity)
    {
        using (var context = new SourceEntities())
        {
            if ( entity.Id == 0 )
            {
                // this is a new record
                context.AppUsers.Add(entity);
            }
            else
            {
                // existing record
                context.AppUsers.Attach(entity);
                context.Entry(entity).State = EntityState.Modified;
            }

            // save the record
            context.SaveChanges();

            return entity.Id;
        }
    }
}
Community
  • 1
  • 1
BeYourOwnGod
  • 2,345
  • 7
  • 30
  • 35
  • What effect did you expect to see? – phoog May 25 '16 at 17:36
  • Well, if I were to remove the where TEntity : class, IEntity part of the interface signature what would happen? Better yet, what is the benefit of having that as part of the signature? – BeYourOwnGod May 25 '16 at 17:37
  • 1
    Do you know what generic type constraints are (or rather why you would use them)? – Kenneth K. May 25 '16 at 17:38
  • Obviously not well enough to understand this. Please enlighten me. :-) – BeYourOwnGod May 25 '16 at 17:42
  • Frankly, if I were to remove that part of the interface's signature, I don't think the code I have written in the implementation would change at all. Hence, my questions on this... – BeYourOwnGod May 25 '16 at 17:43
  • 1
    I'll assume you know what generics are. Generics allow you to generalize the functionality of a class or method to apply to multiple different types, without you having to recreate the class for each difference in typing. But, what if you have a generic class or method that only works (well) with certain types? Without type constraints, you would not be able to limit this class or method to a subset of types; it would apply to every type in .NET, including your own. Using type constraints, you can say that only certain types make sense to use with a particular generic class or method. – Kenneth K. May 25 '16 at 17:45
  • Thank you Kenneth! I believe I get it now. Too bad I cannot mark this as the answer...If you post it as an answer I will mark it as the accepted answer. – BeYourOwnGod May 25 '16 at 17:51
  • In general, as nozzleman points out, the constraint on the interface is not really necessary. It's much more useful in a generic class, where it will enable you to call members of the constraining type on variables of the constrained type parameter. – phoog May 25 '16 at 18:01
  • My question was marked as a duplicate of "What does “T” mean in C#?". I don't think it is a duplicate. I wasn't asking what T means. I know what T means. I wanted to know what the benefits are of that IRepository class signature. – BeYourOwnGod May 26 '16 at 23:28

1 Answers1

2

I think you are doing right by questioning the purpose of that IEntity interface. Doing things just because other people do so it is cargo-cult, if you ask me.

Adding interfaces, just for the purpose of abstraction, is adding superflous complexity. Ask yourself one question: Will you ever use IEntity in your code without caring about what type you are actually processing? If not, I suppose not to abstract that part. If you do, why not?

By looking at your code, it is perfectly clear what your Repository is doing. Don't change that just for the purpose of doing it.

For further reading, see this blog post.

Update

IMO, if your repository needs the ability to "GetById", this could be a pro-argument for such an interface. On the other hand, why not implementing a Find method which accepts a expression to search an Entity?

Generally speaking, I prefer implementing abstract repositories for general purposes, and derived repositories for special needs of certain classes.

nozzleman
  • 9,529
  • 4
  • 37
  • 58
  • I tend to agree. I generally put the type constraints on generic *classes,* but only if I need the constraint for the compiler. I'll generally leave them off the interface. In one of my projects, I spent hours *removing* overly-restrictive constraints when I realized that I could make the model more abstract than it had been. – phoog May 25 '16 at 17:59