0

In one mock solution, I have created 3 mock projects to implement layered architecture design mainly the - Presentation Layer (Web) - Domain Model Layer - Infrastructure Layer. I haven't yet to add Application Service Layer (Web API).

For simplicity, I have only two domain model entities: Customer.cs and Category.cs. In my domain model layer, I also put my repository interface (both custom and generic).

In Infrastructure layer, I have the dbcontext, Unit of Work (including its interface) and repository classes (which implement repository interface).

enter image description here

Here is my generic repository interface

public interface IRepositoryGeneric<TEntity> where TEntity : class
{
    // CRD
    void Add(TEntity entity);
    void Remove(TEntity entity);
    TEntity Get(object Id);
    IEnumerable<TEntity> GetAll();

    void Save();
}

Generic Repository class

public class RepositoryGeneric<T> : IRepositoryGeneric<T> where T : class
{
    protected readonly AppDbContext db;
    public RepositoryGeneric(AppDbContext db)
    {
        this.db = db;
    }

    public void Add(T entity)
    {
        db.Set<T>().Add(entity);
    }

    public T Get(object Id)
    {
        return db.Set<T>().Find(Id);
    }

    public IEnumerable<T> GetAll()
    {
        return db.Set<T>().ToList();
    }

    public void Remove(T entity)
    {
        db.Set<T>().Remove(entity);

    }

    public void Save()
    {
        db.SaveChanges();
    }
}

Unit of Work Interface

public interface IUnitOfWork : IDisposable
{
    IRepositoryCustomer Customers { get; }
    IRepositoryCategory Categories { get; }

    int Save();
}

Unit of Work Class

public class UnitOfWork : IUnitOfWork
{
    private readonly AppDbContext db;
    public UnitOfWork()
    {
        db = new AppDbContext();
    }

    private IRepositoryCustomer _Customers;
    public IRepositoryCustomer Customers
    {
        get
        {
            if (this._Customers == null)
            {
                this._Customers = new RepositoryCustomer(db);
            }
            return this._Customers;
        }
    }

    private IRepositoryCategory _Categories;
    public IRepositoryCategory Categories
    {
        get
        {
            if (_Categories == null)
            {
                _Categories = new RepositoryCategory(db);
            }
            return _Categories;
        }
    }

    public void Dispose()
    {
        db.Dispose();
    }

    public int Save()
    {
        return db.SaveChanges();
    }
}

I learned that I should not have the update method in my generic repository interface. But without update method, I am now stuck at edit method in my presentation MVC web controller. Below, I extracted just the edit action method. The error is in that line in bold.

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "CategoryID,CategoryName,Description")] Category category)
    {
        if (ModelState.IsValid)
        {
            **db.Entry(category).State = EntityState.Modified;**
            db.Save();
            return RedirectToAction("Index");
        }
        return View(category);
    }

Lastly, are my classes created in the right layer? Example should IUnitOfWork.cs be in Infrastructure layer?

My whole solution source is available at my github - https://github.com/ngaisteve1/LayeredArchitectureDesignCSharp

  • I don't know where you heard that you can't have an edit or update method in your repository, but you can. Problem solved. In fact, your Save() method is effectively an update. – Robert Harvey Jun 5 at 15:26
  • Sorry, I mean how do I track the state changes before save? – Steve Jun 5 at 21:53
  • Finally, I fixed state changes issue – Steve Jun 5 at 22:25
0

Generic Repository interface

public interface IRepositoryGeneric<TEntity> where TEntity : class
{
    // CRD
    void Add(TEntity entity);
    void Remove(TEntity entity);
    TEntity Get(object Id);
    IEnumerable<TEntity> GetAll();

    void UpdateState(TEntity entity);
    void Save();
}

Repository generic class

public class RepositoryGeneric<T> : IRepositoryGeneric<T> where T : class
{
    protected readonly AppDbContext db;
    public RepositoryGeneric(AppDbContext db)
    {
        this.db = db;
    }

    public void Add(T entity)
    {
        db.Set<T>().Add(entity);
    }

    public T Get(object Id)
    {
        return db.Set<T>().Find(Id);
    }

    public IEnumerable<T> GetAll()
    {
        return db.Set<T>().ToList();
    }

    public void Remove(T entity)
    {
        db.Set<T>().Remove(entity);

    }

    public void UpdateState(T entity)
    {
        db.Entry(entity).State = EntityState.Modified;
    }

    public void Save()
    {
        db.SaveChanges();
    }
}

Web Controller

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "CategoryID,CategoryName,Description")] Category category)
    {
        if (ModelState.IsValid)
        {
            db.Categories.UpdateState(category);
            db.Commit();
            return RedirectToAction("Index");
        }
        return View(category);
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.