0

I'm about to show my inexperience here, but hey - like any developer I want to learn.

Given the following interface:

public interface IRepository
{
    entityDB Database { get; set; }

    IQueryable<T> All<T>() where T:class, new();
    T Single<T>(Expression<Func<T, bool>> expression) where T : class, new();
    IList<T> Find<T>(Expression<Func<T, bool>> expression) where T : class, new();
}

How would I go about creating a usable repository class such that I can have the generic type T replaced with a strong type?

Assuming I have a photo portfolio site that has a Photos entity and a CameraSettings entity, how do I define the types - and therefore the L2S - that gets included in my concrete class? Currently when I implement the class, it expects the following form:

public class PhotoRepository : IRepository
{
    public override IQueryable<T> All<T>()
    {
        // code goes here...
    }

    public override T Single<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression)
    {
        // ...and here...
    }

    public override IList<T> Find<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression)
    {
        // ... and let's not forget here.
    }
}

Am I even going about this the right way, or should I be using an interface that looks like this:

public interface IRepository<T> where T:class
{
    entityDB Database { get; set; }

    IQueryable<T> All();
    T Single<T>;
    IList<T> Find();
}

I just want to get my unit tests working correctly and be confident that I'm not learning bad (or just plain ugly) habits. Appreciate the steer in the right direction.

1
  • I don't think I need to. I agree with the approach taken by Preben Huybrechts. Commented Jul 12, 2012 at 0:00

2 Answers 2

2

If I've understand you right you want create separate repositories for every your entity (or just for a few of them). In this case appropriate solution is to use the second version of the interface that you posted. Like this:

public interface IRepository<T> where T : class, new()
{
    entityDB Database { get; set; }

    IQueryable<T> All();
    T Single(Expression<Func<T, bool>> expression);
    IList<T> Find(Expression<Func<T, bool>> expression);
} 

And implementation of PhotoRepository will look like this:

public class PhotoRepository : IRepository<Photo>
{
    public IQueryable<Photo> All()
    {
        // code goes here...
    }

    public Photo Single(Expression<Func<Photo, bool>> expression)
    {
        // ...and here...   
    }

    public IList<Photo> Find(Expression<Func<Photo, bool>> expression)
    {
        // ... and let's not forget here.   
    }
}

Also if your repositories will operate with the Entity Framework entities you can define the IRepository interface more exactly:

public interface IRepository<T> where T : EntityObject, new()
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. Being new to EF I figured there'd be something more specific that was a better implementation.
2

In my project, I've created my own IRepository:

public interface IRepository<T>
{
    //Retrieves list of items in table
    IQueryable<T> List();
    IQueryable<T> List(params string[] includes);
    //Creates from detached item
    void Create(T item);
    void Delete(int id);
    T Get(int id);
    T Get(int id, params string[] includes);
    void SaveChanges();
}

Here is generic implementation:

public class Repository<T> : IRepository<T> where T : EntityObject
{
    private ObjectContext _ctx;

    public Repository(ObjectContext ctx)
    {
        _ctx = ctx;
    }


    private static string EntitySetName
    {
        get
        {
            return String.Format(@"{0}Set", typeof(T).Name);
        }
    }

    private ObjectQuery<T> ObjectQueryList()
    {
        var list = _ctx.CreateQuery<T>(EntitySetName);
        return list;
    }

    #region IRepository<T> Members

    public IQueryable<T> List()
    {
        return ObjectQueryList().OrderBy("it.ID").AsQueryable();
    }

    public IQueryable<T> List(params string[] includes)
    {
        var list = ObjectQueryList();

        foreach(string include in includes)
        {
            list = list.Include(include);
        }

        return list;
    }

    public void Create(T item)
    {
        _ctx.AddObject(EntitySetName, item);
    }

    public void Delete(int id)
    {
        var item = Get(id);
        _ctx.DeleteObject(item);
    }

    public T Get(int id)
    {
        var list = ObjectQueryList();
        return list.Where("ID = @0", id).First();
    }

    public T Get(int id, params string[] includes)
    {
        var list = List(includes);
        return list.Where("ID = @0", id).First();
    }

    public void SaveChanges()
    {
        _ctx.SaveChanges();
    }

    #endregion

}

If you want simple repository, you just use Repository<ClassName>. If you want to enhance it, you can define ClassNameRepository : Repository<ClassName> and write another methods. You don't have to define List() method in every repository, because it is done in base. Before writing my repository I made assumptions:

  • Every primary key field in my database is called ID.
  • Every EntitySetName is constructed from class name and Set. For User class it will be UserSet.

This solution uses Dynamic LINQ:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

It works pretty well.

1 Comment

I like this. It looks clean and pretty reusable. Might have to give it a go. Cheers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.