0

I am following along a simple enough YouTube tutorial (link here) on the repository design pattern using MVC. Its good but he uses MVC5 and EF6 which has a lot of support for Async methods.

I am using MVC4 and have had major problems anytime I try to upgrade the project to use EF6. So I just use EF5 but this is not the question.

I altered the code in his tutorial to not use Async as follows (his original code is in comments):

public interface IGenericRepo<TEntity>
{
    IQueryable<TEntity> GetAll();

    //Task<TEntity> GetByIdAsync(int id);
    TEntity GetById(int id);

    IQueryable<TEntity> SearchFor(Expression<Func<TEntity, bool>> predicate);

    //Task EditAsync(TEntity entity);
    void Edit(TEntity entity);

    //Task InsertAsync(TEntity entity);
    void Insert(TEntity entity);

    //Task DeleteAsync(TEntity entity);
    void Delete(TEntity entity);
}

Here is the code (repository) generated by the interface after have done some basic implementations:

public class GenericRepo<TEntity> : IGenericRepo<TEntity> where TEntity : class
{
    protected DbSet<TEntity> DbSet;
    private readonly DbContext dbContext;

    public GenericRepo() { }

    public GenericRepo(DbContext dbContext)
    {
        this.dbContext = dbContext;
        DbSet = dbContext.Set<TEntity>();
    }

    public IQueryable<TEntity> GetAll()
    {
        return DbSet;
    }

    //public async Task<TEntity> GetByIdAsync(int id)
    public TEntity GetById(int id)
    {
        //return await DbSet.FindAsync(id);
        return DbSet.Find(id);
    }

    public IQueryable<TEntity> SearchFor(Expression<Func<TEntity, bool>> predicate)
    {
        return DbSet.Where(predicate);
    }

    //public async Task EditAsync(TEntity entity)
    public void IGenericRepo<TEntity>.Edit(TEntity entity)
    {
        dbContext.Entry(entity).State = EntityState.Modified;
        //await dbContext.SaveChangesAsync();
        dbContext.SaveChanges();
    }

    //public async Task InsertAsync(TEntity entity)
    void IGenericRepo<TEntity>.Insert(TEntity entity)
    {
        DbSet.Add(entity);
        //await dbContext.SaveChangesAsync();
        dbContext.SaveChanges();
    }

    //public async Task DeleteAsync(TEntity entity)
    void IGenericRepo<TEntity>.Delete(TEntity entity)
    {
        DbSet.Remove(entity);
        //await dbContext.SaveChangesAsync();
        dbContext.SaveChanges();
    }
    #endregion
}

Again his tutorial stuff is in comments. After some iterations I eventually arrived at the above but now I am getting a problem when I try to use the last 3 methods. Here is 2 methods working GetAll and GetById. They appear in intellisense but the Insert one doesn't.

    GenericRepo<Course> repo = new GenericRepo<Course>(new SchoolDemoEntity());

    // GET: /Course/
    public ActionResult Index()
    {
        return View(repo.GetAll()); //This works
    }

    // GET: /Course/Details/5
    public ActionResult Details(int id = 0)
    {
        Course course = repo.GetById(id); //This works

        if (course == null) return HttpNotFound();

        return View(course);
    }

    // POST: /Course/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Course course)
    {
        if (ModelState.IsValid)
        {
            repo.Insert(course); //This fails to show in intellisense and obviously I get a red underline.
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(course);
    }

I am assuming (perhaps wrongly) that said methods are private by default which is why they don't appear when I use them like he recommends on the controller (the others appear in intellisense but the last three don't even after building).

So my first taught, make them public right...I did put public access modifier in front of them but then I got this error:

"The modifier 'public' is not valid for this item"

If I don't add public, I cant use it, but if I do, I get an error. I obviously cant add this to the interface so I would really like to know how to fix this please.

Thanks in advance.

Francis Rodgers
  • 4,565
  • 8
  • 46
  • 65
  • OKay, so two places you should look. [My Blog](https://web-dev.ghost.io/concept-conceptual/) and [My Post on SO](http://stackoverflow.com/questions/24992369/asp-net-c-sharp-services-using-irepository-and-each-other), read all the comments – Callum Linington Oct 11 '14 at 21:31

2 Answers2

3

It would seem you have explicitly implemented the interface methods that you say aren't working:

void IGenericRepo<TEntity>.Insert(TEntity entity){...}

Try:

public void Insert(TEntity entity) {...}

Instead

jaywayco
  • 5,846
  • 6
  • 25
  • 40
  • Thank you for your answer. I would like to add that I simply clicked implement interface option which done the whole thing automatically. So why would it do it like this? – Francis Rodgers Oct 11 '14 at 17:51
  • You would implement explicitly when, for example, you implement 2 interfaces that have a method with the same signature. [This](http://stackoverflow.com/questions/4103300/why-implement-interface-explicitly) answer highlights a use case well – jaywayco Oct 11 '14 at 18:11
0

The last two methods are not public methods. Declare them as public methods which then will be accessible.

Venkatesh
  • 1,204
  • 1
  • 10
  • 18
  • Problem 1: You cant declare public / private in the interface. Problem 2: When I declared them as public in the generated class I got the error described at the end of the question. Hence the question. Thanks for taking the time to answer but it doesn't answer the question posed. – Francis Rodgers Oct 12 '14 at 16:16