C# – Avoid core layer referencing DAL when defining repository interface

Architecturecentity-frameworkrepository

I'm trying to learn the N-Layer architecture and several other things, and I have a C# solution where I have the following layers:

  • Core/Infrastructure (Folder)
    • Core (Project)
      • Service interfaces
      • Domain models
      • Repository interfaces
  • Business Logic Layer (Folder)
    • Services (Project)
      • Different services
  • Data Access Layer (Folder)
    • DatabaseAccess (Project)
      • Entities generated via Entity Framework from existing database
      • Different repositories
  • Presentation Layer (Folder)
    • Shell (Project using Prism)
    • Different modules (Multiple projects acting as prism modules)

Does this setup seem correct?

It should pretty much mimic the following image:
enter image description here

When structured like this, it seems very loosely coupled, however, an issue arises when I want to define a repository interface for an entity. The issue obviously being that I would have to reference the DAL project in order to use the entity in the interface… I can't figure out where I've gone wrong or what steps to take to correct this issue.

The generic repository interface in Core.Repositories:

public interface IRepository<TEntity> where TEntity : class
{
    TEntity GetByID(int ID);
    IList<TEntity> GetAll();
    IList<TEntity> Find(Expression<Func<TEntity, bool>> predicate);

    void Add(TEntity entity);
    void AddRange(IList<TEntity> entities);

    void Update(TEntity entity);

    void Remove(TEntity entity);
    void RemoveRange(IList<TEntity> entities);
}

An example repository interface where said issue would arise (Also in Core.Repositories):

interface IChildRepository : IRepository<ChildEntity> //In order to use ChildEntity I would have to add a reference to the DAL project
{
    IList<Child> GetAllChildren();
}

So in conclusion, should I not be using the repository pattern in this case, or what steps can I take to rectify the issue?

UPDATE:

A video I had seen about the repository pattern was somewhat incorrect and was the reason I had an error in my understanding of the pattern and an error in my code. I figured out what the issue was from finding a very nice blog post about the repository pattern.

I am creating specific repositories, but I'm using the generic repository as a helper, so that I don't need to repeat stuff like "GetAll", "Add", or "Find".

When defining my interface I should have done this:

interface IChildRepository
{
    IList<Child> GetAllChildren();
}

And then in my class:

class ChildRepository : Repository<ChildEntity>, IChildRepository
{
    IList<Child> IChildRepository.GetAllChildren() => GetAll().ToModels();
}

Obviously I need to repeat some code like "GetAllChildren", "GetAllParents", & etc. – I guess I'll just have to live with that.

Best Answer

Its correct. but your repositories should return business objects, not database 'entities'

Secondary point. Generic repositories are somewhat frowned upon. Its best to have specific repositories with methods that allow you to make full use of the database to retrieve the exact data you need.

Simplified diagram

  • Models and Interfaces (core) no dependencies
  • Repository, references Models
  • App (presentation layer?), references Models and Repository
Related Topic