Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core, database-first. How to move generic repository interface to another assembly?

I use this tutorial to create a Database model.

I decided to create another assembly for abstractions such as IRepository, IFooService by reading this quote of "Programming .NET Components" by Juwal Lowy:

Because interfaces can be implemented by multiple components, it's good practice to put them in a separate assembly from that of the implementing components.

My solution structure could look like this:

PersonsApp.Solution
--PersonsApp.WebUI
   -- Controllers (PersonController)
--PersonApp.Common
   --Core folder
      -IGenericRepository.cs (Abstraction)
      -IUnitOfWork.cs (Abstraction)  
   --Repositories folder
      -IPersonRepository.cs (Abstraction)
--PersonApp.Persistence  
  --Infrastructure folder
      -DbDactory.cs (Implementation)
      -Disposable.cs (Implementation)
      -IDbFactory.cs (Abstraction)
      -RepositoryBase.cs (Abstraction)
  --Models folder(Here we have DbContext, EF models (Implementation))      
      -Person.cs (Implementation)
      -PersonContext.cs (Implementation)
  --Repositories folder
      -PersonRepository.cs (Implementation)

However, PersonApp.Persistence project has a reference to PersonApp.Common. But my project PersonApp.Common also needs a reference to PersonApp.Persistence because I would like to create a IPersonRepository.cs in Person.Common:

public interface IPersonRepository : IRepository<Person> {}

The following error is thrown, when I try to add a reference to PersonApp.Persistence into PersonApp.Common:

A reference to 'PersonApp.Persistence' could not be added. Adding this project as a reference would cause a circular dependency.

However, I really would like to have separate assembly for interfaces and another assembly for Entity Framework.

How can I move repository interface to another assembly?

In addition, I would like to be able in future to keep the database schema in sync with the EF Core model by preserving data.

I use DatabaseFirst. Thank in advance. Any help would be greatly appreciated!

like image 775
Learner Avatar asked Sep 08 '19 11:09

Learner


1 Answers

I'm going to be the outcast here and give you an answer you may not like, and probably most of the other people on the thread won't either. The answer is... don't use repositories.

Years ago when it was the most popular thing in the universe, I tried it out. I spent months trying to understand it, implement it, and use it. To this day I still can't understand the benefit vs complexity of implementation when it comes to repositories. In the end I stopped trying and removed them from any projects I had. I never looked back.

I'm sure someone will contest my statement, but that's just my experience, and I feel that the OP is going down the path of the dark times in my development history.

As far as your project structure, I'd recommend the following:

PersonsApp.Solution
-- PersonsApp (optional)
   -- Extensions/ (any root-level extensions you want available to the other projects)
-- PersonsApp.Data
   -- references PersonsApp
   -- Configurations/ (contains all IEntityTypeConfiguration<T> for your POCOs)
   -- Models/ (contains all of your POCOs)
   -- DbContext.cs
-- PersonsApp.Web
   -- references PersonsApp and PersonsApp.Data
   -- Extensions/ (DbContext extensions to project data the same way you would with a repository, without the repository and with less code)
   -- ??? (your controllers, views, etc to display your app to your users)

This now solves your circular dependency.

I'd also recommend you looking into Jimmy Bogard's Vertical Slices Architecture using MediatR. It blew my mind when I first learned of it and it's been amazing working with it, unlike the overly complicated DDD architecture.

In my case the PersonsApp.Web structure would look like this:

-- PersonsApp.Web
   -- Features/ (all vertical slices)
   -- Resources/ (all scripts and styles that will be compiled by Gulp into the wwwroot folder)
   -- Program.cs
   -- Startup.cs

I took the vertical slices a step further with AutoMapper and Entity Framework Plus' Future Queries. Shameless self plug to my blog talking about it. It is a bit outdated though, but a decent starting point. I should update it soon.

like image 166
Gup3rSuR4c Avatar answered Oct 18 '22 13:10

Gup3rSuR4c