locked
How to use Generic Repository Pattern with DbContext + DbSet generics RRS feed

  • Question

  • In many of the samples/blogs, we see the creation of a custom class that extends DbContext, e.g. in the EF.CodeFirst.Walkthrough samples we have

      public class SimpleBookCatalog : DbContext
      {
        public SimpleBookCatalog(DbModel model)
          : base(model)
        { }
        public DbSet<Book> Books { get; set; }
        public DbSet<Person> People { get; set; }
        public DbSet<Author> Authors { get; set; }
        public DbSet<Publisher> Publishers { get; set; }
      }
    


    What I'm trying to accomplish is to create a generic repository

    // Non Generic One
    public class BookRepository 
    {
      public Book Retrieve(int id)
      {
     SimpleBookCatalog.Books.Where(x=>x.Id == id);
      }
    }
    // I want to create a generic one, like this
    public class RepositoryBase<T>
    {
      public T Retrieve(int id)
      {
     // DbSet<T> MyDbSet = ??? What goes here?
     MyDbSet.Where(x=>x.Id == id);
      }
    }
    

    How do I do the above? In LINQ 2 SQL, I would do something like this:

    Table<T> MyTable = MyDataContext.GetTable<T>;
    MyTable.Where (x=>x.Id == id);
    

     

    Suggestions or sample code would be greatly appreciated.

    Thanks.

    Wednesday, December 22, 2010 6:47 PM

Answers

  • Okay, so I found the problem -- I had to do something like this:

    public abstract class RepositoryBase<T> 
    where T: class
    {
    ...
    }
    

     

     

     

    Now, I'm able to use

    _dbContext.Set<T>() without any problems.

    • Marked as answer by iam_ray Thursday, December 23, 2010 8:52 PM
    Thursday, December 23, 2010 8:52 PM

All replies

  • Ray,

     

    Assuming you have a DbContext configured with your model in some way, then you can use the Set<> method.  For example:

     

            public T Retrieve (int id)

            {

                return _dbContext.Set<T>().Where(x => x.Id == id);

            }

     

    Note that instead of using a LINQ query you can use the Find method to find an entity by primary key:

     

            public T Retrieve (int id)

            {

                return _dbContext.Set<T>().Find(id);

            }

     

     Find has advantages over a LINQquery such as it will return an entity from the context if it exists there without hitting the database.

     

    Thanks,

    Arthur

    Thursday, December 23, 2010 7:17 PM
    Moderator
  • Can you show me an example of how you configured DbContext? I tried using the generic you proposed, but I get a compiler error that "T must be a reference type in order to use it as a parameter for TEntity"

    Thanks,

    Ray

    Thursday, December 23, 2010 8:35 PM
  • Okay, so I found the problem -- I had to do something like this:

    public abstract class RepositoryBase<T> 
    where T: class
    {
    ...
    }
    

     

     

     

    Now, I'm able to use

    _dbContext.Set<T>() without any problems.

    • Marked as answer by iam_ray Thursday, December 23, 2010 8:52 PM
    Thursday, December 23, 2010 8:52 PM