Francis Rodgers
Francis Rodgers

Reputation: 4675

Interface problems with repository design pattern in C# MVC4 and EF5

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.

Upvotes: 0

Views: 385

Answers (2)

Venkatesh
Venkatesh

Reputation: 1224

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

Upvotes: 0

jaywayco
jaywayco

Reputation: 6286

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

Upvotes: 3

Related Questions