What is a Repository pattern and why should we use it?
With the Repository pattern, we create an abstraction layer between the data access and the business logic layer of an application. By using it, we are promoting a more loosely coupled approach to access our data from the database. Also, the code is cleaner and easier to maintain and reuse. Data access logic is in a separate class, or sets of classes called a repository, with the responsibility of persisting the application’s business model.
Implementing the repository pattern is our topic for this post. Additionally, this article has a strong relationship with EF Core, so we strongly recommend reading our EF Core tutorial to get familiar or just a better understanding of that topic.
VIDEO: Repository Pattern in ASP.NET Core Web API video.
If you want to see all the basic instructions and complete navigation for this series, please follow the following link: Introduction page for this tutorial.
For the previous part check out: Creating .NET Core WebApi project – Custom logging in .NET Core
So, let’s start
Creating Models
Let’s begin by creating a new Class Library project named Entities
and inside it a new folder with the name Models
, which will contain all the model classes. Model classes will represent the tables inside the database and will serve us to map the data from the database to the .NET Core. After that, we should reference this project to the main project.
In the Models folder, we are going to create two classes and modify them:
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Entities.Models { [Table("owner")] public class Owner { public Guid OwnerId { get; set; } [Required(ErrorMessage = "Name is required")] [StringLength(60, ErrorMessage = "Name can't be longer than 60 characters")] public string? Name { get; set; } [Required(ErrorMessage = "Date of birth is required")] public DateTime DateOfBirth { get; set; } [Required(ErrorMessage = "Address is required")] [StringLength(100, ErrorMessage = "Address cannot be longer than 100 characters")] public string? Address { get; set; } public ICollection<Account>? Accounts { get; set; } } }
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Entities.Models { [Table("account")] public class Account { public Guid AccountId { get; set; } [Required(ErrorMessage = "Date created is required")] public DateTime DateCreated { get; set; } [Required(ErrorMessage = "Account type is required")] public string? AccountType { get; set; } [ForeignKey(nameof(Owner))] public Guid OwnerId { get; set; } public Owner? Owner { get; set; } } }
As you can see, there are two models decorated with the attribute Table(“tableName”)
. This attribute will configure the corresponding table name in the database. All the mandatory fields have the attribute [Required]
and if we want to constrain the strings, we can use the[StringLength]
attribute. In the Owner
class, we have the Accounts
property which suggests that one Owner
is related to multiple Accounts
. Additionally, we add the OwnerId
and the Owner
properties decorated with the [ForeignKey]
attribute to state that one Account
is related to only one Owner
. If you want to learn more about the EF Core configuration, and we strongly suggest you do, visit the Configuring Nonrelational Properties in EF Core.
Context Class and the Database Connection
Now, let us create the context class, which will be a middleware component for communication with the database. It has DbSet
properties that contain the table data from the database. For a better understanding of the Context class and DbSet properties and how they work with EF Core overall, you can read Getting Started with EF Core article.
At the root of the Entities
project, we are going to create the RepositoryContext
class and modify it:
using Entities.Models; using Microsoft.EntityFrameworkCore; namespace Entities { public class RepositoryContext: DbContext { public RepositoryContext(DbContextOptions options) :base(options) { } public DbSet<Owner>? Owners { get; set; } public DbSet<Account>? Accounts { get; set; } } }
Pay attention that you have to install Microsoft.EntityFrameworkCore
package.
To enable communication between the .NET core Web API application part and the MySQL database, we have to install a third-party library named Pomelo.EntityFrameworkCore.MySql
. In the main project, we can install it with the NuGet package manager or the Package manager console. Make sure that the Pomelo version is the same as the version of the EF Core library you installed. If the Pomelo full published version is not the same as the EF Core version, just use the prerelease version – it should be ready to use – as we did in the source code.
After the installation, let’s open the appsettings.json
file and add DB connection settings inside:
{ "Logging": { "LogLevel": { "Default": "Warning" "Microsoft.AspNetCore": "Warning" } }, "mysqlconnection": { "connectionString": "server=localhost;userid=root;password=yourpass;database=accountowner;" }, "AllowedHosts": "*" }
In the ServiceExtensions
class, we are going to write the code for configuring the MySQL context.
First, let’s add the using directives and then add the method ConfigureMySqlContext
:
using Microsoft.EntityFrameworkCore; using Entities; public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config) { var connectionString = config["mysqlconnection:connectionString"]; services.AddDbContext<RepositoryContext>(o => o.UseMySql(connectionString, MySqlServerVersion.LatestSupportedServerVersion)); }
With the help of the IConfiguration config
parameter, we can access the appsettings.json
file and take all the data we need from it.
Afterward, in the Program
class, let’s add the context service to the IOC right above the services.AddControllers()
:
services.ConfigureMySqlContext(builder.Configuration);
Repository Pattern Logic
After establishing a connection with the database, it is time to create a generic repository that will serve us all the CRUD methods. As a result, all the methods can be called upon any repository class in our project.
Furthermore, creating the generic repository and repository classes that use that generic repository is not going to be the final step. We will go a step further and create a wrapper around repository classes and inject it as a service. Consequently, we can instantiate this wrapper once and then call any repository class we need inside any of our controllers. You will understand the advantages of this wrapper when we use it in the project.
First, let’s create an interface for the repository inside the Contracts
project:
namespace Contracts { public interface IRepositoryBase<T> { IQueryable<T> FindAll(); IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression); void Create(T entity); void Update(T entity); void Delete(T entity); } }
Right after the interface creation, we are going to create a new Class Library project with the name Repository
, add the reference from the Contracts
and Entities
projects, and inside the Repository
project create the abstract class RepositoryBase
which will implement the interface IRepositoryBase
.
Add the reference to this project inside the main project too.
Let’s add the following code to the RepositoryBase
class:
using Contracts; using Entities; using Microsoft.EntityFrameworkCore; using System.Linq.Expressions; namespace Repository { public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : class { protected RepositoryContext RepositoryContext { get; set; } public RepositoryBase(RepositoryContext repositoryContext) { RepositoryContext = repositoryContext; } public IQueryable<T> FindAll() => RepositoryContext.Set<T>().AsNoTracking(); public IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression) => RepositoryContext.Set<T>().Where(expression).AsNoTracking(); public void Create(T entity) => RepositoryContext.Set<T>().Add(entity); public void Update(T entity) => RepositoryContext.Set<T>().Update(entity); public void Delete(T entity) => RepositoryContext.Set<T>().Remove(entity); } }
This abstract class, as well as IRepositoryBase
interface, uses generic type T to work with. This type T
gives even more reusability to the RepositoryBase
class. That means we don’t have to specify the exact model (class) right now for the RepositoryBase to work with, we are going to do that later on.
Repository User Classes
Now that we have the RepositoryBase
class, let’s create the user classes that will inherit this abstract class. Every user class will have its own interface, for additional model-specific methods. Furthermore, by inheriting from the RepositoryBase
class they will have access to all the methods from the RepositoryBase
. This way, we are separating the logic, that is common for all our repository user classes and also specific for every user class itself.
Let’s create interfaces in the Contracts
project for our Owner
and Account
classes.
Don’t forget to add a reference from the Entities
project to the Contracts
project. As soon as we do this, we can delete the Entities
reference from the main project because it is now provided through the Repository
project that already has the Contracts
project referenced, with the Entities
reference inside.
using Entities.Models; namespace Contracts { public interface IOwnerRepository : IRepositoryBase<Owner> { } }
using Entities.Models; namespace Contracts { public interface IAccountRepository : IRepositoryBase<Account> { } }
Now, let’s create a repository user classes in the Repository
project:
using Contracts; using Entities; using Entities.Models; namespace Repository { public class OwnerRepository : RepositoryBase<Owner>, IOwnerRepository { public OwnerRepository(RepositoryContext repositoryContext) :base(repositoryContext) { } } }
using Contracts; using Entities; using Entities.Models; namespace Repository { public class AccountRepository : RepositoryBase<Account>, IAccountRepository { public AccountRepository(RepositoryContext repositoryContext) :base(repositoryContext) { } } }
After these steps, we are finished with creating the repository and repository user classes. But there are still more things to be done.
Creating a Repository Wrapper
Let’s imagine that inside a controller we need to collect all the Owners and collect only certain Accounts (for example Domestic ones). We would need to instantiate OwnerRepository
and AccountRepository
classes and then call the FindAll
and FindByCondition
methods.
Maybe it’s not a problem when we have only two classes, but what if we need logic from 5 different classes or even more? Having that in mind, let’s create a wrapper around our repository user classes. Then place it into the IOC and finally inject it inside the controller’s constructor. Now, with that wrapper instance, we may call any repository class we need.
Let’s start by creating a new interface in the Contract
project:
namespace Contracts { public interface IRepositoryWrapper { IOwnerRepository Owner { get; } IAccountRepository Account { get; } void Save(); } }
After that, we are going to add a new class to the Repository
project:
using Contracts; using Entities; namespace Repository { public class RepositoryWrapper : IRepositoryWrapper { private RepositoryContext _repoContext; private IOwnerRepository _owner; private IAccountRepository _account; public IOwnerRepository Owner { get { if(_owner == null) { _owner = new OwnerRepository(_repoContext); } return _owner; } } public IAccountRepository Account { get { if(_account == null) { _account = new AccountRepository(_repoContext); } return _account; } } public RepositoryWrapper(RepositoryContext repositoryContext) { _repoContext = repositoryContext; } public void Save() { _repoContext.SaveChanges(); } } }
As you can see, we are creating properties that will expose the concrete repositories and also we have the Save()
method that we can use after all the modifications are finished on a certain object.
This is a good practice because now we can, for example, add two owners, modify two accounts, and delete one owner, all in one method, and then just call the Save
method once. All changes will be applied or if something fails, all changes will be reverted:
_repository.Owner.Create(owner); _repository.Owner.Create(anotheOwner); _repository.Account.Update(account); _repository.Account.Update(anotherAccount); _repository.Owner.Delete(oldOwner); _repository.Save();
In the ServiceExtensions
class, we are going to add this code:
public static void ConfigureRepositoryWrapper(this IServiceCollection services) { services.AddScoped<IRepositoryWrapper, RepositoryWrapper>(); }
And in the Program
class, above the services.AddControllers()
line, add this code:
builder.Services.ConfigureRepositoryWrapper();
Excellent.
Testing
All we have to do is test this code the same way we did with our custom logger in part 3 of this series.
Inject the RepositoryWrapper
service inside the WeatherForecast
controller and call any method from the RepositoryBase
class:
[ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private IRepositoryWrapper _repository; public WeatherForecastController(IRepositoryWrapper repository) { _repository = repository; } [HttpGet] public IEnumerable<string> Get() { var domesticAccounts = _repository.Account.FindByCondition(x => x.AccountType.Equals("Domestic")); var owners = _repository.Owner.FindAll(); return new string[] { "value1", "value2" }; } }
Of course, we didn’t implement our OwnerRepository and AccountRepository classes so we won’t see any data, but this shows an advantage of our RepositoryWrapper class.
In the next part, we are going to show you how to restrict access to the RepositoryBase
methods from the controller, if you don’t want them to be exposed here.
Conclusion
The Repository pattern increases the level of abstraction in your code. This may make the code more difficult to understand for developers who are unfamiliar with the pattern. But once you are familiar with it, it will reduce the amount of redundant code and make the logic much easier to maintain.
In this post you have learned:
- What is a repository pattern
- How to create models and model attributes
- How to create context class and database connection
- The right way to create repository logic
- And the way to create a wrapper around your repository classes
Thank you all for reading this post and I hope you read some useful information in it.
See you soon in the next article, where we will use repository logic to create HTTP requests.
Can you explain the rationale behind using a class library? Presumably re-useability across different databases/api’s ?
I’m creating an API that serves AdventureWorks2017 data.
Should I put the class library in the Solution or outside it ?
Hi Robert. Yes, reusability is the main reason. Regarding your project, if you plan to use some features of the project, like interfaces or repositories, or a shared project with your DTOs then you can create new class libraries. But if nothing will be shared or reused, you can use folders in the same solution.
Thanks for the article. I am having an issue where in the ServiceExtention.cs class, inside the ConfigureMySqlContext the MySqlServerVersion is not being recognized.
Moreover, it says: The name ‘MySqServerVersion’ does not exist in the current context.
Not sure if the Pomelo package was installed in the wrong repo, but I have it in the main project ‘AccountOwnerServer’.
Stuck on where I slipped up!
Hello Kent. You have the link to the source code at the beginning of the article. It was updated to .NET 6 and everything worked there. So you can download it and compare it with your solution. That said, I hope Pomelo didn’t change anything for the .NET 7 support.
Hi, I appreciate you are sharing those tutorials
I Have 3 patch API With 3 different Dto For modified One Entity :
which approach is better
1- Create 3 services For Modified with 3 different DTOs (All Those Methods are the same)
2- Create 1 Service For Modified With One Dto Called “EditDto” And Map Those 3 DTOs To EditDto
3- Create 1 Service For Modified With Entity As param and And Map Those 3 DTOs To Entity
From my own experience, I would never create the method with the same functionality three times. I would always try to create one reusable method
Hi
please i have 4 tables related by parent child, i need help to make repository and service and controller for two table i can do it like company and employee example but for other i stuck.
example: compnay / employee /children /child-games (each one depend on prior one)
api/{id company}/employees that i can do it, but
api/{id company}/{id employee}/children i stuck
if i can do :
api/{id employee}/children
and
api/{id children}/child-games
please any ideas or help i will apreciate it !
thanks
For example, if your children entity is dependent on the employee and the employee is dependent on the company then the full main URI for the children controller should be: api/companyId/employeeId/children. Both the companyId and employeeId, you should get from the main route and if you have additional actions in the children controller that requires additional parameters, you will have to get them on that specific action. For example, if you now need children by id action, you will have something like this: [HttpGet(“{id}”)]
public IActionResult GetChildrenById(Guid companyId, Guid employeeId, Guid id)
Where the first two id parameters you will map from the main route.
You can read the rest of our articles from this series for additional details. The link to the next article is at the end of this article.
thanks what about the fourth table wich depends on the third table children
what about findby to get all children by two parameter companyid adn employeeid if you can give me example
thanks a lot
Hi Marinko, thanks for your great article.
Exactly It is something for which I was looking for, but in controller this code
[ var department = _repoWraper.Department.FindByCondition(x => x.DepID.Equals(id)); ]
producing error as below
InvalidOperationException: The model item passed into the ViewDataDictionary is of type ‘Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[DMSMISv09._2022_Entities.Models.Department]’, but this ViewDataDictionary instance requires a model item of type ‘DMSMISv09._2022_Entities.Models.Department’.
Pls suggest how to fix it
Regards
Hi Merchant. I am sorry, but I don’t know why you have this error. Obviously, you have your own project but you can download our source code and compare those two to see the implementation differences in your project.
Hi Marinko, thank you for your great article.
Is it okay to use IQueryable directly within the Repository Pattern like you did?
Is it not a leak to expose data ?
Of course, it is okay to do it that way. You should use IQueryable as long as you querying the database. Once the query is done you should get the data with ToList or any other loading method.
Surly best Series ever. <3 thanks
You are most welcome.
public WeatherForecastController(IRepositoryWrapper repository) { _repository = repository; }
If there is 100 repo in Wrapper, is it a good approach?
I see no problem with it except that you have 100 repo classes.
Interesting post
Hi guys, thanks for all the great posts. I am using your RepositoryWrapper pattern to group all my repository interfaces but I find that DI appears to automatically be filling in all the interfaces automatically. So that when a call to the ‘get’ property on say Owner the backer property is already filled in. That seems contrary to the purpose of the generation only at request time. Am I doing something wrong that would automatically DI everything in the wrapper?
Hello Dan. Well, I am not aware of your implementation, but if you are using this implementation, from this article, you are only registering the IRepositoryWrapper in IOC and nothing else. All the repository objects will be created only when you request for them, that’s why we didn’t inject them as well but we are creating a new instance for each. You can use the Lazy class as well, as we do in our second edition Web API book.
Thanks for the response Marinko. For testing purposes to make sure I didn’t configure anything wrong in my own code, I tested using your part 4 AccountOwnerServer project. This is .NET 6 using Visual Studio 2022 Community. On my machine, if you were to set a break point on WeatherForecastController.cs line 14 (constructor where you set the internal _repository) you will notice on construction the wrapper already has both Account and Owner repositories created. You can verify this is the case by setting breakpoints on RepositoryWrapper.cs line 17 & 29 (where you instantiate new OwnerRepository and AccountRepository classes). Neither of these will get hit as the internal variables were already constructed. It APPEARS that DI/IoC is automatically instantiating both the child interfaces automatically. Seems counter to what we really want (like you I would prefer that the repositories only get instantiated at call rather than DI’d). Possibly this is a new .NET 6 / VS 2022 thing? Thank you!
Hi Dan. But this is not DI. Once you create a repository object, you will have exposed both public properties Owner and Account, this is how things work in C#. But the main point is that both _owner and _account variables are null. And then when you call the _repository.Account… (inside the controller) at that moment you will instantiate the AccountRepository and you can inspect the _owner object is still null because we didn’t call it at all. So, public properties will be accessible, but your repository objects are still not populated until you call them. As I said, you can do it this way or by using the Lazy class.
Maybe this is just on my two machines with .NET 6 / VS 2022, but using your part 4 sample code only (no changes) and debugging, when I set a breakpoint on the forecast class constructor and inspect the passed in repository both _owner and _account are not null, they’ve been instantiated and I don’t know how. Sorry, not trying to be testy, I think your writing is awesome and the wrapper class is a brilliant way to do it, I WANT it to work as in my own code I need access to multiple repositories and don’t want to have to request each…but for some reason at least for me, it’s not working 🙁 Thanks.
A snapshot of the controller constructor and the _owner / _account already instantiated
Well, I think there is something wrong with VS. This project is in .NET 6. Don’t place a breakpoint inside the controller, but just inside the Owner and Account properties in the Wrapper class. You should see both are null when a request arrives.
It could very well be VS 2022, I actually set a breakpoint at the same spot, but at least for me it’s filled in (as in, not null), I also set a breakpoint at _account = new AccountRepository… and it never ever gets hit, it’s always non-null. I’ll keep testing / playing and see if I can figure out what’s going on. Thanks for all your time
Hi, Thanks for such a great post.
Am new in .net so during implementation, i got this error when am adding interface in Contract.Please guide me
Since this is a part of the .NET Core series, I strongly suggest you read all the articles from that series. That way you won’t miss a thing in implementation. What may cause your error is a missing reference from the Entities project inside the Contracts. We added that one in the third part of the series regarding the logger implementation. This is the link to the entire series https://code-maze.com/net-core-series/ (but you have it linked in this article as well).
yes its fixed now, Thank you sir.
how to call store producer and database fucntion in dotnet core
This really depends on what you are using to access your database. If you are using Dapper you can check this article: https://code-maze.com/using-dapper-with-asp-net-core-web-api/ If you are using EF Core, you can use FromSql or ExecuteSqlCommand methods to do so…
This is not my question i am asking how to do this with repository pattern i unit of work generic repository in entity Framework work not in dapper
Well to be 100% precise here, your question was, and I quote: “how to call store producer and database fucntion in dotnet core”, so I replied to what I was asked for.
Regarding your second question, you can do that in many different ways, either to create your own separate methods in the repository user classes or to create a base method that will accept the name of the procedure and all the parameters (using params[]) and then create custom logic to execute that procedure and return required values. Again, this is something related to your own implementation and it depends on how you want things to be done.
Hi, Marinko. I followed your code and I have an error in ServiceExtensions when I used method AddScoped in ServiceCollection when I register wrapper repository . I try replace AddScoped with AddSingleton method but I get again error.
Do you have this inheritance in your code: public class RepositoryWrapper : IRepositoryWrapper
Thanks Marinko, that’s it 🙂
Marinko, I still have a problem.
I created a database in mysql like yours only with different tables and data. I have 3 tables. Following your code I came to a test where from the controller I call the wrapper repository to get me the data from the database. The problem is that I’m not getting data from the database but I’m getting null?
When I start an application with a set breakpoint the postman only continuously sends a data request but when I remove the breakpoint the postman retrieves the string “value1” and “value2” from the controller.
Can you give me some advice to solve the data retrieval? Thank you in advance.
appSettings.json
Hello Darko. Well, it is hard for me to know what is the issue. But, have you tried finishing the series (reading the other two articles) then, you would have a bit more knowledge about the HTTP requests and how to handle all the CRUD operations. Maybe it will even help you to resolve your issue.
Thank you for your replay. I haven’t gone trought two articles related to http request so I ‘ll throw myself into that now.
Hello, just wondering what the point of adding all this into different Class Libraries?
Hello Rygar. With this structure it is easier to maintain the code, to share the projects that you can reuse in other projects, multiple people can work on different libraries at the same time, etc.
Using Entity Framework for this example just overcomplicated a simple concept. MOst of the comments I’ve read all stem from issues with EF, and not the IOC or general Reposity pattern.
Hello Jeff. Well if you know what you are doing, there will be no issues at all. You have to know EF Core in order to work with it. Once you are familiar, you won’t have any issues whether you use it directly or through any abstraction. The main point is that this is the way how we like and how we think the Repository Pattern should be created.
Hi, Marinko Spasojevic, if i have 10 repository, should i put all of them into the repositorywrapper, if not, what’s the better way? Thanks
Yes. This wrapper provides access to all of them with a single object.
Hi, thanks for the great tutorial. I have a question regarding how to properly do DI when we are using the wrapper. We are instantiating the concrete object with _owner = new OwnerRepository(_repoContext); and passing in the _repoContext into the constructure. However what if I want to pass other things in using DI into OwnerRepository, ILogger for example – how would I go about doing that?
Hello Mat. To do that just inject it inside the wrapper class and pass it as a parameter to the required repository class. Then inside the repo class just provide the readonly field, provide parameter in the constructor, and assign the value from the parameter to the field. That is it.
Hi, Marinko. I’m the third time in this article) And it is my new question. How to take data from two tables in repository pattern?
Hi Ivan. Maybe this article can help you with that: https://code-maze.com/queries-in-entity-framework-core/
how login funtion work in repositry??
If you are using Identity to provide login functionality for you, then this layer has nothing to do with it. Otherwise, if you are creating your own custom auth process, I see no problem integrating that inside the repo layer as we did with the company or account classes.
Hello Marinko, at the start of this tutorial series, you have specified that we will be foloowing Db first approach. But here , we are creating the model classed by ourselves & also the context. Why so?
*following, *classes
Hello Dibyo. I am sure that you probably think why don’t we use the EF Core mechanism to create models and the context class for us but doing that manually. To be clear, this is still a db first approach. We already have the database and we are creating our models based on that database. Also, by doing this manually, we can explain the process step by step and it is easier to understand what each part of the process means.
Okay, so by creating the models manually (it’s still using Db first approach ,as you said) we don’t have to run migration right?, Automatically the model classes will get mapped to Db tables, right?
That is correct. When you want to use migrations, you prepare connection string, model classes, and db context, run migration command and it will create migration files for you which you can execute to create a database and also populate tables. This way, you already have the db with populated tables. As you can see in the article, no migration is needed. If you want to read more about EF Core migrations, you can read this article: https://code-maze.com/migrations-and-seed-data-efcore/
Hello Marinko, What is the best (or you can say official) Db provider for MySql Database using EF Core in Production level projects? Here you are using Pomelo.EntityFrameworkCore.MySql, but isn’t there any other official DB provider like for Sql Server we have Microsoft.EntityFrameworkCore.SqlServer?
Maybe this can help you https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework-core.html
For me, Pomelo did a great job.
Hi Marinko, I read your post, and it’s very interesting. Thank you for this great article.
You mentioned that the wrapper repository is used in a large application where you need to deal with/collect data from multiple classes/entities.
In my company we develop large applications as well and use Repository-Service pattern to handle this use case; where the Service is used to collect data from multiple classes/entities.
I’ve been using repository-service pattern for 5 years now and works well.
So my question is now, what is the difference between wrapper repository and repository-service pattern ?
Also if you can point out any pros and cons for each method (wrapper repository and repository-service pattern).
Regards
Jonhson
Hello Johnson.
First, I must say that I never wrote that the repository wrapper is used in large apps. You should use it in small or large apps since it behaves as UoW.
Now, the thing you are talking about is the service layer, so it is another layer and that can’t be compared to the RepositoryWrapper class. This article is only about the repository pattern and we didn’t want to add the service layer to it. But, we do recommend using the service layer and injecting RepositoryWrapper there and not in the controller. The main job of RepositoryWrapper is to bind all the repositories in a single class, so you could inject only one class into the service and also control the execution of each individual repository, as explained in this article.
We’ve already linked the Onion Architecture article inside this article, but here it is again: https://code-maze.com/onion-architecture-in-aspnetcore/ There, you will see how to combine this repository pattern with the service layer.
Hi Marinko, thank you a lot for this great post.
I just want to know whether I can use this wrapper repository technic in a regular ASP.Net Core MVC application, with no Web API included ?
Also create some topics related to advanced development in ASP.Net Core MVC or Web API or C# ?
Hello Alice.
Yes, you can use it with any app you want.
Regarding your suggestion about the advanced topics, could you specify what would you like to see exactly? We have some advanced topics regarding API and C#, but additional suggestions are always welcome.
Great course
Thanks a lot. I’m glad you like it.
its created manually ServiceExtensions class ?
That is correct.
which is batter i read your book you use
==========================
IQueryable<T> FindAll();
IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression);
void Create(T entity);
void Update(T entity);
void Delete(T entity)
============================
as generic repository when you make async function why you not convert this to async like this
Task<IQueryable<T>> FindAll();
Task<IQueryable<T>> FindByCondition(Expression<Func<T, bool>> expression);
Task Create(T entity);
Task Update(T entity);
Task Delete(T entity)
also tell me which approch is batter
If you’ve read our book then in section 14.2.1 you can find why we didn’t convert that as well to an async code.
what if we want to use both of is it wrong approch like blow
==========================
IQueryable<T> FindAll();
IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression);
void Create(T entity);
void Update(T entity);
void Delete(T entity)
Task<IQueryable<T>> FindAllAsync();
Task<IQueryable<T>> FindByConditionAsync(Expression<Func<T, bool>> expression);
Task CreateAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(T entity)
============================
If you want to support both options and it gets a job done for you, it is just fine by me.
Why don’t you have SaveChanges() method in the RepositoryBase abstract class?
The RepositoryBase class is not a place for the SaveChanges method. It doesn’t work as UnitOfWork. If you put that method there, you would have to call it only inside the repository user classes, which is wrong. You want to call that method after all of the repository actions that modify the state of your entities, are executed. That’s exactly the point of UoW.
Understood
Thanks for your reply
code is awesome, but i dont want class level generics i need method level
can you please send code to my mail if you have .
Hello, Marinko! I have written this method, but I don’t know if it is well. What you think about it?
public async Task AreFriends(string userId, string friendId, bool trackChanges)
{
return await FindByCondition(t =>
t.FirstFriendId == userId && t.SecondFriendId == friendId && t.Confirmed ||
t.FirstFriendId == friendId && t.SecondFriendId == userId && t.Confirmed,trackChanges).AnyAsync();
}
Well, by the first look at it, it seems fine to me. The AnyAsync will return true or false if your collection contains elements or not. To test it, you can always split it up. First return the result of the collection without AnyAsync and then extract the result of the AnyAsync method. That way you can check if it is working right step by step.
How to delete ICollection from Parent Entity class using RepositoryBase<> ? If chile entity have [Owned] attribute.
I do like the generic approach. Much more use of separate projects and extensions than I’ve been using. I can live with it though.
Hi Marinko! Thanks. I have a question.
You used “AddScoped” while adding all services “services.AddScoped();”
but we use for some service -> Singleton or Transient
How can we do that?
Thanks again.
Hi Orphan.
I am not sure, how can you do what?
Hi Marinko,
Thanks for this tutorial. I’m getting exception after this step in RepositoryContext constructor
“System.InvalidOperationException: ‘The database provider attempted to register an implementation of the ‘IRelationalTypeMappingSource’ service. This is not a service defined by Entity Framework and as such must be registered as a provider-specific service using the ‘TryAddProviderSpecificServices’ method.’
I have added Microsoft.Bcl.AysncInterfaces (5.0.0) to Repository project – because of the first exception I got saying it was missing. Then I replaced polemo (pkg for MySQL that was specified) package with MySql.Data.EntityFrameworkCore (8.0.22) because of another comment I saw here. When I googled the above error one suggestion was to switch to SQL Server – which I can do – but I wanted to see if there is a fix for MySQL first.
TIA,
Carol
Hello Carol. I must say that error is not known to me. The code from this article should work without a single problem. After the EFCore update to version 5 (if you use .NET 5) you have to use prerelased pomelo version qnd slightly change the UseMySql method. I’ve added all the nites in the article. So there is no need for changing a library if you want to use MySQL. If you read the Pomelo GitHub page, you will see that they are developing a version 5.0.0 as we speek so, we don’t have to use the prerelease version.
Hi Marinko,
Thanks for the quick reply. I’m using .Net Core 3.1. I removed Microsoft.Bcl.AysncInterfaces package and the MySql.Data.EntityFrameworkCore (8.0.22) and put back in Pomelo package. So I’m back to the original exception that happens when I try to test by going to the web page. The exception is “System.IO.FileNotFoundException: ‘Could not load file or assembly ‘Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51′. The system cannot find the file specified.’
If you don’t know the fix for this or have any other ideas can you tell me what I need to change to try with SQL Server?
TIA
It sounds to me as if you have used some different namespace or something. It is really hard for me to say like this. My best suggestion is to download our source code, you have the link on top of the article, and compare your solution to mine. You will find some difference for sure. You can even test our solution to see that it works. You don’t have to switch to SQL, but if you want to do it, don’t use the UseMySql method, uninstall Pomelo, and use the UseSqlServer method instead.
Hi Marinko,
thanks for all in depth resources you provide, you’re my only light in decision making while setting up new projects for my company and I’m not experienced, yet overwhelmed by the amount of information and path to take.
Anyway, do you refer to the RepositoryWrapper class as Unit of Work class? I see that this is usually the common approach, maybe you’re only using a different nomenclature.
Hello Ivan. Thanks for the kind words, that means a lot. Yes, you are right, the RepositoryWrapper class is exactly that. Just it is created my way, but still doing the same thing as UoW.
Nice, thanks for the reply! In my scenario I have a big database behind an ERP and other software, with lots of tables. What I’ll usually have to do is to interact with lots of tables and joins, resulting in operations using lots of tables. Do you think that in this scenario should I provide another layer above the repository layer, such as a service layer querying multiple repositories? This can become really cluttered? Do you thing that a viable approach could be like “compressing” the repository layer by only using EF core and then using those entities scaffolded from the database in my services, having complex queries?
Using a Service layer is always a good practice. Keep all the db related logic in the repository layer and all the business logic move to the service layer. Since you have a lot of tables, having a service layer should be a good practice. Basically if you have to extract something form the db and than do something with that data and then again fetch data from the database and do something else with that result combining it with the previous one… than the service layer is a must. You don’t want your repository layer to have any kind of business logic, just fetch the data and get back the result, leave all the rest to the service layer, inject it in the controller and from there just call the methods from a service layer and return results to the client.
Very clear answer, thank you! I’ll take advantage of your answer for another little question:
Am I right if I always make services return and accept Dto objects? Because I’m building a general web service living inside my company private LAN, so my thought was to build all the stuff discussed behind services and then employ services inside razor pages (in Blazor Server) but eventually reuse them behind rest api controllers; in that way I’d almost abstract away everything, meaning that if I build an api controller then its only concern would be to pass Dtos invoking services, while at the same time using these services and Dtos produced inside razor pages (Blazor), employing them as “ViewModels” useful also for validating inputs inside a form or for example making a login interface.
That’s a good practice. In our book our advice is exactly that. Use model objects only to interact with the DB. For the requests (body params) and the responses you should be using DTOs.
Thank you very much. Code-maze is my new headquarter for .NET knowledge 🙏
Hi Marinko,
Thanks for sharing your tutorials; they are an incredible resource for rookies like me! But I’m really stuck trying to implement the Repository Wrapper to my little hobby project…apologies if I get the language wrong in my explanation but this is still all pretty new to me…
Instead of injecting the wrapper in my Controller, I’ve added it in my Services layer, which sits in between my Repositories and Controllers. For example:
public class UserService : IUserService // fyi IUserService inherits from IBaseService
{
private readonly BaseRepositoryWrapper _baseRepositoryWrapper;
public UserService(BaseRepositoryWrapper baseRepositoryWrapper)
{
_baseRepositoryWrapper = baseRepositoryWrapper;
}
// methods
}
Then from my UsersController I inject IUserService:
public class UsersController : ControllerBase
{
private readonly IUserService _service;
public UsersController(IUserService service)
{
_service = service;
}
// methods
}
(Side question: why do I use the interface rather than the class? switching it doesn’t solve my problem though!)
And in my Startup ConfigureServices I have:
services.AddScoped();, UserRepository>();();();, UserService>();
services.AddScoped
services.AddScoped
services.AddScoped
services.AddScoped
The wrapper works beautifully allowing me to access all my different repos within the UserService methods and the project builds without errors. However, I get the following exceptions when trying to boot up the UserApi on localhost:
“Some services are not able to be constructed
(Error while validating the service descriptor ‘ServiceType: MFP.Api.Services.IUserService Lifetime: Scoped ImplementationType: MFP.Api.Services.UserService’: Unable to resolve service for type ‘MFP.Api.Repositories.BaseRepositoryWrapper’ while attempting to activate ‘MFP.Api.Services.UserService’.)
(Error while validating the service descriptor ‘ServiceType: MFP.Api.Services.IBaseService`1[MFP.Models.User] Lifetime: Scoped ImplementationType: MFP.Api.Services.UserService’: Unable to resolve service for type ‘MFP.Api.Repositories.BaseRepositoryWrapper’ while attempting to activate ‘MFP.Api.Services.UserService’.)”
Is there anything you can spot I’m doing wrong or suggest I try? Any guidance would be much appreciated! (Let me know if I haven’t provided enough information for you to work out what I’ve messed up!) Many thanks!
Hello. As much as I can see, if you followed the implementation forom my article, you shouldn’t be registering the BaseRepository class as a service. It is an abstract class meant only for inheritance. So, remove that registration from the Startup class. Only user repository classes inherits from it. Regarding the interfaces, you use them to allow easier dependency injection and to provide object decoupling. It is a part of the SOLID principles (the “I” part).
I took 5 mins to refresh my cup of tea and there was your reply when I got back! Thanks for spotting my incorrect service registration of the BaseRepository, which I’ve now removed from my Startup, but unfortunately I’m still getting the same error messages.
I tried removing the IUserService and IBaseService registrations, which then allowed the localhost to launch but with an error webpage declaring:
Unable to resolve service for type ‘MFP.Api.Services.IUserService’ while attempting to activate ‘MFP.Api.Controllers.UsersController’
But as soon as I try registering a service with an interface dependency, I get the original aforementioned errors in Visual Studio relating to the BaseRepositoryWrapper. I thought maybe registering the UserService with the BaseRepositoryWrapper interface or class might be the issue but I can’t get that to work because ‘there is no implicit conversion’ between the two‘.
Do you have any other ideas that I can investigate and try to play with?
FYI I thought I’d go back to the less slick option so replaced the BaseRepositoryWrapper with UserRepository instead but am actually hitting pretty much the same error so it looks like my problem is unrelated to the wrapper…the hunt continues!
First of all, you can’t remove the UserService registration because you use it in the controller with DI. So it has to be registered as a scoped service in your case. But, from the code you posted, I can’t find anything else. The error states there is the problem with the BaseRepositoryWrapper registration, but I can’t tell what is the problem. You can share the code on the GitHub, and I can download it and inspect it. Of course if that doesn’t take a lot of my time. But if it requires more than just a quick look, then we would have to talk about the consultation for sure. It all depends on how you implemented your solution.
Hey Marinko, that would be awesome if you could take a quick look at my code but zero worries if my mistake can’t be found within a few minutes, thanks again for all your help!
https://github.com/deelye/mfp
Btw I’ve just switched my UsersController dependency to the IUserRepository i/o IUserService (so basically my project isn’t calling services/the wrapper anywhere) and the UsersAPI is booting up nicely on my localhost
Sorry, one other thing…switching my UsersController dependency to the RepositoryWrapper also works! but ideally I’d like to get a Services layer with Wrapper DI working
Hi Dee. I found the problem. You are using the BaseRepositoryWrapper class as a constructor parameter inside the UserService constructor, but you should be using the interface:
public class UserService : IUserService
{
private readonly IBaseRepositoryWrapper _baseRepositoryWrapper;
public UserService(IBaseRepositoryWrapper baseRepositoryWrapper)
{
_baseRepositoryWrapper = baseRepositoryWrapper;
}
After this change, your project starts and I am getting a result in the browser.
oh Marinko, you’re amazing! thank you SO much for figuring out my stupid error! i hope lots of good karma comes your way for the hugely appreciated help 🙂
Hi Marinko,
Great article and I plan to implement much of it.
I’m not sure if you’ve mentioned it, I’m wondering your opinion about implementing a separate “Unit of Work” interface. One popular YTer, “Mosh”, suggests this. He suggests implementing both IRepository and IUnitOfWork. Just curious your view. Thanks again!
Hi Kevin. Mosh the great 😀 He has the point, you should do that. But we are doing it here, just I don’t want to call it UnitOfWork. In our example it is RepositoryWrapper. As you can see, from that class you can call all the other repository classes and for each entity in your model schema you can use the singe Save() method, which will apply changes in the db. Basically, this is our version of UoW.
Thanks for the quick response!
I’ve been following this tutorials for a while and they’re absoluty amazing. But i have a problem right now. I need to run some unit tests with this logic and it’s getting really confusing. Do you have a tutorial for that?
Hello Pablo. We have a series about testing in ASP.NET Core MVC: https://code-maze.com/asp-net-core-mvc-testing/ . I am sure the knowledge can be implemented in this application for sure because in this series you can find how to create unit tests, how to test controllers and how to create integration tests. Maybe that can help you out.
I red all your unit test articles but i still can’t find a way to test my controllers using IRepositoryWrapper. I always get an “Object reference not set to an instance of an object.” error on IRepositoryWrapper.User.get
Yeah, I understand you. For the IRepositoryWrapper you need some abstractions in your testing class. It’s not that simple for me to try to explain it here. As much as I can remember (didn’t do that for quite some time) you have to mock it and provide a RepositoryContext object inside, to avoid receiving null exception.
IT does seem that even with the abstractions added using Moq, that even though the mocked repo objects have data in them the RepositoryContext object’s Set() call returns null. Driving me nuts, wish I had a solution. EDIT: As soon as I posted, I found something that might be a solution: https://stackoverflow.com/questions/25569382/ef6-dbsett-returns-null-in-moq
Thank you very much for the link. This will help our readers for sure.
Hello Marinko,
First of all thanks for such a great post.
Friendly note, inside the RepositoryWrapper Class you create a dependent object “_owner = new OwnerRepository(_repoContext);” is it better to use Dependency Injection.
Hello Chefai. This is so common question about this article or the video that I should update the article with the explanation. So, I will not tell you whether you should use this setup or use dependency injection, I will tell you why I did it this way.
For example, if a user asks for all owners, they will hit the OwnerController and GetAllOwners action (this is implemented in the next article of the series). In the GetAllOwners action, you will have expression like this: _repository.Owner.GetAllOwners. What this does? It uses the injected _repository object (RepositoryWrapper type) and only instantiates the OwnerRepository object inside it, not the AccountRepository object, and finally calls the method from the OwnerReopsitory class. So this is important part, only OwnerRepository class.
Now, if you register both OwnerRepository and AccountRepository as services with their respective interfaces, and inject them inside the RepositoryWrapper class, as soon as the _repository object gets injected inside the Controller or any Service, both OwnerRepository and AccountReopsitory will be created as well. And that is something I tried to avoid.
So again, I am not telling you this is a way to do it, as I am not telling anyone to use RepositoryPattern (you know the popular opinion about not using it with EF Core), all I try to do is to show how I think it should be implemented or to help anyone creating their own modified implementation 😀
I hope this explanation helps.
thank you for your response, i am using generic repository pattern with EF, and your posts helped me a lot.
I’m using ASP.NET 5.0 Preview.
I got this error on Pomelo. I’ve install the latest version https://uploads.disquscdn.com/images/d53f13c62876af91486e92964d58d3d2e24d25f8b720a25b0d60ef4b08b398fe.jpg
Hello. Well, as you can see the Pomelo version is 3.1.2.0 so it probably doesn’t have a support for the .NET 5 yet. We didn’t test it yet, because .NET 5 is still in preview and exactly this kind of problems can appear. Once the .NET 5 is official, we are going to modify this series for sure. I am sure the Pomelo will be updated as well. You can check here for yourself https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql . It has only support for EFCore 3.1 and lower.
Thanks, Mr. Marinko!
Write a book on Blazor Framework next time. 🙂
Well that is a good sugestion 🙂 Right now, we are publishing the Blazor WASM series but everything is on the table. Thank you for reading and suggestion.
Hey, first of all, amazing tutorial series!.
how to restrict access to the RepositoryBase methods from the controller ???
I mean how i can show only FindAll and hide Update And Delete
Thank you
Hi Dean. We are glad you like the series. In the next article, we explain exactly that, so feel free to read it. It is just about interfaces. Thank you for reading. Best regards.
Excellent article. I have used it to do some tests. However, I am faced with a question of how to do something.
I need to create an entity in the repository that accesses more than one datacontext, for example, in addition to accessing the context of my database, it has to use an api rest and another api soap. In total, three contexts.
But I want to keep only the wrapper injected into the controller.
How can this scenario be implemented in your model?
thanks a lot
Well the solution on top of my head is to wrap these three context classes with a single context wrapper, register that wrapper class and inject it in the RepoWrapper class, instead of the RepositoryContext class. That way, you are passing a single object to the user repo classes and there you can decide wich context to use. Additionally, you can use couple of interfaces for that context wrapper so you could restrict the access from the repo classes, if you don’t want all the repo classes to access all the context objects.
I have implemnted this fine for MS SQL Server, exactly as listed – no mods, but when, using Pomelo, I run it for MYSQL I get the following error in the RepostoryContext class – annotated against “base(options)”
System.TypeLoadException: ‘Method ‘Create’ in type ‘Pomelo.EntityFrameworkCore.MySql.Query.ExpressionVisitors.Internal.MySqlSqlTranslatingExpressionVisitorFactory’ from assembly ‘Pomelo.EntityFrameworkCore.MySql, Version=3.1.1.0, Culture=neutral, PublicKeyToken=2cc498582444921b’ does not have an implementation.’
Any ideas?
Why would the abstract Create do it’s job for MSSQL but not MYSQL?
Thanks in anticipation!
Hello Duncan. If you are working with the MSSQL database, you don’t need Pomelo at all. It is required only for the MySQL because it is MySQL driver. So, don’t use it for the MSSQL database, EF Core provides everything you need for that.
Many thanks.
MSSQL is fine – obv without Pomelo – but I want it to work for MYSQL – with Pomelo.
And that’s when the problem happens.
I’m sorry, I didn’t understand your question well. I thought you were trying to use Pomelo with MSSQL. One more time my appologies. I can always suggest to download our source code and compare it with yours. If you can’t find the problem, you can upload the code and I can check it out. But, I am not sure why do you have that problem. Also try using the same library versions as we did in the Video to make sure that this is not the version problem.
ok, thanks. The code is exactly as yours, and works fine for MSSQL, no errors at all. The only changes are then to include Pomelo and change the DB connection to
services.AddDbContext(o => o.UseMySql(MYSQLconnectionString));
or (to align with how MSSQL is now working)
services.AddDbContext(o => o.UseMySql(MYSQLconnectionString, sqlServer => sqlServer.MigrationsAssembly(“Entities”)));
Both come up with the same error as detailed before.
I will check package versions etc, but am a bit stumped as all are latest.
Many thanks.
MSSQL is fine – obv without Pomelo – but I want it to work for MYSQL – with Pomelo.
And that’s when the problem happens.
Super job on the repository pattern tutorial. Got everything working perfectly. First time using MySQL i had to figure out how to start the database but that was easy. I think things have evolved a little with Entity Framework Core. I don’t remember having to add this as a service in the project. Also the foreign key is something I have used before in the model. Seems like a step toward domain model and enforcing relational rules before sending bad requests and getting referential integrity violations.
Hello Marinko,
Thanks for the great tutorial.
I have a problem testing at this point, trying to inject the RepositoryWrapper in the WeatherForecast
public ValuesController(IRepositoryWrapper repoWrapper)
{
_repoWrapper = repoWrapper;
}
The error said “Method must have a return type” (on the ValuesControlle function)
Any ideas please
Hello Jose Luis. Please remove the ValuesController name and add WeatherForecastController (constructor should have the same name as a class), as it is now in the article. This typo happened when we updated this series to 3.1 version, earlier it was ValuesController but now it is WeatherForecastController. Sorry for this. Best regards.
Hello!
I would like to ask about transaction. If I use a WrapperRepository how can I get context to make transaction?
For example:
_wrapperRepo.Owner.CreateOwner(owner);
_wrapperRepo.Save();
_wrapperRepo.Account.CreateAccount(account);
_wrapperRepo.Save();
I need use Save twice because I have to get OwnerId to use it to create account (foreign key). I know I can create two entities in one insert to database but i have trigger on the database which check something so I have to do it this way.
using (var transaction = context.Database.BeginTransaction()) <- How get context from wrapperrepository?
The SaveChanges method executes transaction for you. You don’t have to create it manually. But if you need the manual transaction for some reason, use the RepositoryContext property from the RepositoryBase class and create a method in the user repository class with transactions. Then just call that method with the wrapper: _wrapperRepo.Owner.CreateWithTran()
SaveChanges method executes transaction for me but if _wrapperRepo.Account.CreateAccount(account);
_wrapperRepo.Save(); execution fails I need to _wrapperRepo.Owner.CreateOwner(owner);
_wrapperRepo.Save(); rollback too.
Hey Marinko!
What would be the implementation on the RepositoryBase to allow the utilization of Include and ThenInclude?
Thanks for your time!
Hello. I wouldn’t recommend that. In the RepositoryBase class you should work only with the clear entities. So in this case either owner or account. But as you can see, all the methods return IQueryable which means that in the user repository classes, such as OwnerRepository you can write something like: FindByCondition(u => u.Id.Equals(ownerId)).Include(a => a….)… This is exact purpose of the user repo classes. To transform and hand over results to your Business or Presentation Layer (this depends whether you have a Business Layer in your app). You can find example of this in the next article of this series.
Hello Marinko,
I have a problem that i cannot figure out why it is happening. I have two classes lets call them Foo and Bar. These classes are in one-to-many relationship. The Foo class can contain many Bar classes. The Foo class looks like this:
class Foo {
… some other properties
public Bar bar;
}
class Bar { Foos;
… some other properties
public ICollection
}
Now the problem i have is that when i try to save Bar object that has one or more Foo objects i get an exception Duplicate entry ’08d7b1f5-620a-8599-926f-c001cc5d8b28′ for key ‘Foo.PRIMARY’.
Hello kal. While adding objects to the database, don’t populate the id field on your own. Please have a look how we did it in the sixth part of this series. I don’t have your source code, so I can only assume this is the problem.
My code is the same as the one in this lesson. What i have is a function in controller that calls _repository.Foo.GetFooById(id) two times and gets me two Foo objects from database. Then i add these two Foo objects to bar.Foos collection. Then i call _repository.Bar.CreateBar(bar). And after that _repository.Save(). And i get the exception Duplicate entry ’08d7b1f5-620a-8599-926f-c001cc5d8b28′ for key ‘Foo.PRIMARY’ where the guid is the id of Foo that i got from db.
If i create the seperate repository class without using this generic stuff but just call _context.Bar.Add(bar) this works fine. Something like this works :
public class BarRepository () {
private DbContext _context;
BarRepository(DbContext context) {
_context = context;
}
public void createBar(Bar bar) {
_context.Bar.Add(bar);
_context.SaveChanges()
}
}
What I understood from your explanation, doesn’t have to much sense to me. Whay would you extract data from the database, attach it to a relational entity and then tried to add it back to the same table. You already have an object with the same Id in the database so it is obvious you have that error. If you use a different context, than it doesn’t track changes from a previous context and it allows you the operation, but I’m wondering why the database allows you to add the object with the same id in the same table? Again I have no idea about your implementation, but the thing you do really doesn’t sound right.
What i am trying to do in the context of this lesson is this:
create owner with multiple accounts
So in db i have owner table with owner id
in the accounts table i have a column for owner_id which is foreign key and can be null
So in controller i retrive two accounts that don’t have owner id set
then i create owner and set these accounts in owner.accounts list
then i save owner to db and expect for two accounts from db that i fetched to update their owner_id column to the id of saved owner.
Hi kal. I understand what are you trying to do, but you are doing it wrong. You can’t update entity with the Add method. The Add method adds the state as added to the entity and when you call SaveChanges, EF Core tries to create that entity in the db. If you already have it in the db, as you do, you will get the error. What you can do is as follows:
Fetch those two accounts without owner_id value. Create a new owner in the database and then update these two accounts by adding the id value of newly created owner to those two accounts.
I strongly recommend you reading https://code-maze.com/entity-framework-core-series/ You will learn a lot about EF Core and data manipulation.
Thanks for the explanation Marinko.
Hey, i’m a begginer and i’m having some issues on testing the wrapper on weather forecast, I don’t know how to exatcly explain, but i’m getting no results, and no erros from vs. I can only see the logger test from the previous class.
Thanks so much for this content, it’s realy hellping me to build my dreams!!
Hello Artur. Well my first advice is to download our source code and try to compare it with yours. If you can’t find the issue, you can share your code on GitHub and I could look at it.
Great… Love it.
Thanks. Just keep it rockin’ 😀
Hello Marinko!
Friendly note, inside the Account model there is a problem where the OwnerId is declared twice. Speaking about requiring a request to include a FK, I have ran into this issue before where you cannot add the Required attribute to primary and foreign keys. If you send a request to a ASP.NET Core API endpoint and do not include properties for the PK and FK (even though they have the Required attribute) the request will not be rejected. What are your thoughts on this?
Hello Lagrango. Thank you for that. I forgot to remove that extra part during the code refactoring. Sorry, my bad.
About your problem with required FK and PK, I only can asume that they were of type int. As you know Int is the value type and if you don’t send it as a part of the body object, than it will accept the default value wich is 0. Therefore it won’t be null and it will pass the required check. At least, this is one case that can happen for sure.
One more time thank you and sorry for my bad.
Best regards.
Ahh yes they were of type int. Thanks!
Yeah. That one can be tricky. Use the Range attribute to validate value types. In our book, that is about to come up, or if you are subscriber then you know about that, we talk more about that type of validation. Have a great day.
Hi, thanks for a good article. Your Wrapper seems to act quite similar to what is known in literature as ‘Services’. They would not expose full IOwnerRepository or IAccountReposity however, but rather some business methods that use these repositories under the hood (eg. ‘give me all owners that are male along with their accounts’). What do you think about replacing wrappers with services? Also a Unit of Work pattern could be useful for submitting changes spanning across several repositories.
Hello Marcin. Thank you for reading and for your suggestion. I don’t like to think that wrapper is acting as “Services”, in here it has two functions, to enable single registration in IOC which then we can inject in any Controller or in the Service layer (if we have a bigger app) and use all the methods from the specific user repo class (Owner repo or Account repo or…). The second usage is as Unit of Work, because it shares a single Save method which affects any user repo we are currently using. So it is something in between. My logic is if something is in the interface than that is something I want to expose to the user. Of course, don’t get me wrong, I’m not saying that your idea is bad and mine is the best. NO WAY. I thinnk your idea makes all the sense in the world, but I have to defend my approach 😀 😀 Finally, using service layer is always recommendation and we encourage everyone to do that, but for the project this size, I think it would be an overload. One more time, thank you for the suggestion and all the best.
Thanks!
Hey, first of all, amazing tutorial series! I’ve been following them from the beginning with the MySql database. I’ve implemented my own database which is just a tad bit more complex than the ones in the tutorial, but still very similar.
After completing part 4 and trying to test my program in the weatherforecast. I get the following exceptions at startup.
Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Contracts.IRepositoryWrapper Lifetime: Scoped ImplementationType: Repository.RepositoryWrapper': Unable to resolve service for type 'Entities.RepositoryContext' while attempting to activate 'Repository.RepositoryWrapper'.)
Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: Contracts.IRepositoryWrapper Lifetime: Scoped ImplementationType: Repository.RepositoryWrapper': Unable to resolve service for type 'Entities.RepositoryContext' while attempting to activate 'Repository.RepositoryWrapper'.
Exception 2:
InvalidOperationException: Unable to resolve service for type 'Entities.RepositoryContext' while attempting to activate 'Repository.RepositoryWrapper'.
Been trying to fix it the last couple of hours, but i’m at a loss of how to fix this. Anyone experience anything similar? Any help would be highly appreciated!
Hello Jonas. I’ve been able to recreate your error by simply commenting out the RepositoryContext service registration:
https://uploads.disquscdn.com/images/e00028f3250098c2ca469b2c9ea42275d5b87eabe94a049f484d026ad6a5aa51.png
So, you have a problem with that class – RepositoryContext. My advice is to check if the extension method for the context registration, is the same as ours. As the error states, you have a problem with RepositoryContext registration and due to that your RepositoryWrapper can’t be registered as well. But the main problem is in RepositoryContext registration. Check the connection string or if you extract good params from the appsettings.json file.
If you can’t solve it, you can share your code with us, and we are going to check it out.
I hope this will help you.
Best regards.
Thank you for the quick response. I found the cause of the issue, which was a missing “services.ConfigureMySqlContext(Configuration);” in my ConfigureServices. I’m now able to run the program, however it seems like i can’t get a connection to my MySQL database. Does it require some sort of setup inside VS, aside from what has been show in the tutorial? So far i’ve established the connection using the connectionString, have i missed anything?
Link to my github:
https://github.com/joyde3382/Buginator/tree/master/BuginatorServer
EDIT:
Figured out how to connect the MySQL db with vs19 (was missing the mysql for vs19 extension). Now however i get errors when trying to load data from my entities foreign keys.
“InnerException = {“Unknown column ‘u.RoleId’ in ‘field list'”}”
Were RoleId is a foreign key to my Role entity.
(image of error) https://imgur.com/a/vEJNh1x
Hello Jonas. Well, I don’t know what is your specific error message, but I’ve downloaded your code and ran it locally. It has connection to the database, but you have one problem. I’ve only played with the Project table. Your problem is that you have a Project model class, but without the [Table(“project”)] attribute above that class, you app is targeting your database and the Projects table that doesn’t exist. It does that because your DbSet property is named Projects. It seems that this is the way that Pomelo works. So as soon as I added that attribute on top of the Project table, it worked without a single problem. Try that and let us now the result.
Hmm, didn’t think adding table names were mandatory, but i guess they are in a database first implementation. Nevertheless i tried adding them, but still getting errors when i try to run the program. (The errors doesn’t break the program, it’s just the objects that are not getting loaded with the correct data). When i hover over the objects and try to see the data inside i can read the following errors:
When loading from Users: “Message = “Unknown column ‘u.RoleId’ in ‘field list'””
When loading from Projects: “Message = “One of the identified items was in an invalid format.””
Hello Jonas. Well that’s a logical error. If you check your sql script for the User table, you will find many columns inside and Role_RoleId amongs them. And if you check your User model class, you will find all the different properties and the RoleId amongs them. So, your error states that .net core doesn’t know how to map the RoleId to the User table because it doesn’t have that column (it has Role_RoleId)… So check your model classes against the tables in the database.
https://uploads.disquscdn.com/images/9a7e268e8090c22ba51db3a3b4c1b257a187850af04178a6b04506195028e1a6.png
https://uploads.disquscdn.com/images/e92dd6749aab97fe42253314c280d29338ef2a46fbb80a63696f9e63320dc105.png
Hope this will help you.
Thank you for your help, i got it solved!
You are very welcome. I’m glad I could help. I hope these articles help you as well. Feel free to ask any question, and if you like what you see, you may subscribe to get notified about our new content. Anyhow, thanks for reading our articles. Best regards.
Hello! First of all thank you so much for this amazin article. Secondly, about the Repository Pattern i followed every each step to the letter but when i do the request from Postman the app stops in VS and the output shows
I tried injecting the context class directly into the controller and using it to query the database y everything works fine. So i belive the issue came when using the repository pattern architecture. I realy need a hand on this!
Hello Pablo. I am really willing to help you, but this error doesn’t tell me much. Or at least I don’t know what does it mean. Anyhow, have you tried to download our source code and try to compare with yours. Additionaly try running our source code to see how it works (it must work, 100% sure). Finally, if nothing helps, you can share your code with me, and I can try to figure it out.
I’ve been following this tutorial to the letter (except using my own names). I’m using MySql 8 and Rider 2019.2.
I’ve set up Rider with my database connection and the test flies perfectly. But, trying to run it, I’m getting this:
Microsoft.EntityFrameworkCore.Database.Connection[20004]
An error occurred using the connection to database ‘database’ on server ‘localhost:3306’.
System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found o
r was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could
not open a connection to SQL Server) —> System.ComponentModel.Win32Exception (53): The network path was not found
Hello Eran. Take a look at this part of your message “Verify that the instance name is correct and that SQL Server is configured to allow remote connections”. You can google it and try to find the solution. But for now you can check your connection string and whether your server allows remote connections. It would take too long for me to explain how to do that here, so that’s why I said to google it a bit.
When I test the connection in my database definitions, everything works great. Exactly the same values.
Is there an explanation on exactly how to write a connection string for MySQL?
Hello Marinko, first of all thank you so much for putting together a fine tutorial!
I’m pretty new at all of this and have an error I can’t work out. When I try to test the ‘”GetAllOwners’ method from my Api (I test it with swagger), I get an “Object reference is null” error for my Context property in my RepositoryBase class. The error happens at the call of the ‘FindAll()’ method. My context class is never instantiated and always null when it’s being passed through all the constructors. Any idea what may be causing this?
I’m using Sql local db, the data is there. I used migrations in the Entities project to seed the database.
I configure StartUp class services like this:
services.AddScoped();
services.AddDbContext(opts => opts.UseSqlServer(Configuration[“ConnectionString:RepoDB”]));
Thanks, hope you have enough information. I do have been doing the tutorial with different models, but the logic is all the same.
Never mind, I simply forgot to add a constructor in the RepositoryBase class injecting the context.
Hello JanBA. I am sorry that you are facing that problem and I want to help you but it is not that easy with just two lines of code. Have you checked your connection string, is it good? If you have your code on GitHub repo, you can share it, and than I could inspect it, maybe then I could find your problem. And you are correct, logic is the same whether you use our models or your own.
Hi Marinko. I just want to ask if I call Add method, will it generate the Guid Key that I can use for another class or do I need to call the Save method first before I can access the Key? Is there a way for making DB transactions using this pattern?
Hello. The Add method won’t add the Guid key, it has nothing to do with it. Please read the rest of the series and you are going to see how to insert a new entity with the Add method. All that Add method does is marking your entity with state Added, which tells EF Core that as soon as we call the SaveChanges method, it should be inserted in DB. You have to add your GUID Key manually as we did in the last part of the sereis. Regarding the question about transaction, EF Core provides transaction through the SaveChanges method. Thats why we use it after all the actions are prepared. Either all actions succed or none.
Alright thank you.
If hard coding data access in a controller is a bad thing, based on a number of articles and books I;ve read. W
hy is you architecture doing just that?
Hello RoyB. First of all there is zero of hardcoded repo logic in the controller, just a simple calls of repo methods. But I understand your question and yes, even these calls towards repo logic shouldn’t be placed in a cintroller, but this is a small project and it would be pointless to create another layer between the controller and repo logic. But in a real world (larger) projects, creating a business layer is always a recomendation.
Thank you for your reply. I did enjoy your E-Book.
Hi,
It works perfectly but I have two questions.
How can i handle stored procedures
And Master child scenarios using generic repository.
Hi Marinko.
Please respond.
Hello Hasan, sorry for late response, but I haven’t seen your question at all. About stored procedure EF Core has the FromSql method which allows you to execute raw SQL queries and stored procedures, something like this:
var owners= context.Owners
.FromSql("EXECUTE dbo.GetSomeOwners")
.ToList();
You can use this statement in the owner repository class.
About the master detail, I can’t see any problem with that. Every entity has its own repository user class which inherits from the RepositoryBase class, so the specific logic for specific entities you need to place into the specific repository classes.
Hi Marinko,
I have to update a child collection while a parent is getting updated. Is that okay to write the update code in the “TestRepository” update method?
Code will look like this, it didn’t work as i’m getting exception for having more than one data
public void UpdateTest(Test test)
{
var existingParent = FindByCondition(p => p.Id == test.Id).AsQueryable()
.Include(p => p.CandidateLanguages)
.SingleOrDefault();
// Update parent
RepositoryContext.Entry(existingParent).CurrentValues.SetValues(test);
// Delete children
foreach (var existingChild in existingParent.CandidateLanguages.ToList())
{
if (!test.CandidateLanguages.Any(c => c.Id == existingChild.Id))
RepositoryContext.CandidateLanguages.Remove(existingChild);
}
// Update and Insert children
foreach (var childModel in test.CandidateLanguages)
{
var existingChild = existingParent.CandidateLanguages
.Where(c => c.Id == childModel.Id)
.SingleOrDefault();
if (existingChild != null)
// Update child
RepositoryContext.Entry(existingChild).CurrentValues.SetValues(childModel);
else
{
// Insert child
var newChild = new CandidateLanguage
{
LangId = childModel.LangId,
Mothertongue = childModel.Mothertongue
};
existingParent.CandidateLanguages.Add(newChild);
}
}
Update(test);
RepositoryContext.SaveChanges();
}
Or can you please can suggest a better way of updating the child collection before or after the parent update.
Got the sample from
https://stackoverflow.com/questions/27176014/how-to-add-update-child-entities-when-updating-a-parent-entity-in-ef
Hi. Well to reproduce this code I would need some time and also it would take me a quite a lot of time to explain how Entity Framework Core works with this kind of actions and with tracking changes. So, I will try to explain it quickly if I can:
It looks to me over-complicated. What I saw from this code, you are comparing your object from db with the object Test. All the mutual properties (or child objects) that are changed in the Test object should be updated in db, all the collection objects in the test object that doesn’t exist in the database should be added and all the objects from db that don’t exist in the Test’s collection should be removed. If so, you should retrieve the database object in the controller and use automapper to map test object with all the collection objects to the db object. That will force EF Core to modify the state of all the changed objects to Modified. Then you could write something like this:
var forDelete = existingParent.CandidateLanguages
.Where(e => !test.CandidateLanguages.Select(t => t.Id).Contains(e.Id));
_context.CandidateLanguages.RemoveRange(forDelete);
this would find all the collection objects from db that don’t exists in the Test.Candidates collection and set the state of all these objects to Deleted.
Finally you can do the other way around to find all those that exists in Test.CandidateLanguages and don’t exist in existingParent.CandidateLanguages and for all these objects to call AddRange to set their state to Added. After that you call SaveChanges().
Again I haven’t test this or anything, but I believe it should work and it is exactly how things should be done.
Hi Marinko,
I am using MS SQL SERVER Database. Every thing is working fine but when i call the service i got this error.
Unable to cast object of type ‘System.Data.SqlTypes.SqlString’ to type ‘System.Data.SqlTypes.SqlGuid’.
You have any clue ?
Hello Hasan. Your types are obviously mismatch. For example your Id field in a class is of type Guid and the same column in the table is of type string. The Char(36) is only representation of Guid for the MySQL database. In SQL you have to use Uniqueidentifier type for the Id column.
Thanks it works.
Hi,
A question on repo pattern, i read in few articles that the Save/Update should not be in Repo base, is that right? or this is also a way to do. I’m bit confused.
I have implemented your type of pattern in my application so just wanted to confirm.
Well, the Save method is not in the Base class. About the Update it depends. As you can see we are using always AsNoTracking to retrieve entities and you need the Update method to add it again to the tracking state and to set its state to Modified. So basically if you have disconnected update, then you need the Update method in the Base class. I would always leave it there. But you can modify your get methods with the additional optional parameter to state whether you want to fetch the data with or without tracking. Then if you fetch them with tracking you don’t need to call the Update method, just to map changes and call Save.
Aah.. makes sense, Thank you!
Hi Marinko, many thanks for the great tutorial.
I am new to this and have been following a couple tutorials. You use the Pamelo libraries however, I also followed a tutorial that used the MySQL.Data.EntityFrameworkCore instead. That project was also a DB first approach.
So, I’m now a bit puzzled about which approach I should be taking. Do you use Pamelo because there are limitations to the MySQL library?
I appreciate your assistance on this matter.
Hello. To be honest, when I started using MySQL with .NET Core, its been a while, I found the Pomelo library, tried it, made entire project with it, and everything worked great. So I just didn’t explore any further.
You can read more here https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/issues/112
As I said, this library worked great for me, and that is pretty much it 😀
All the best.
Thanks, Marinko – appreciate your time.
I am using Entity Framework for core, Do i Still need any third party like Pomelo.EntityFrameworkCore.MySql to talk to database ?
If your database is MySql, as it is in this tutorial, then you need Pomelo. If your database is MSSql then EF Core is enough on its own.
Found the bug
One question : in startup.cs we are calling services.ConfigureMySqlServerContext(Configuration); but the call goes to public static void ConfigureMySqlServerContext(this IServiceCollection services, IConfiguration config)
Which context is this ? Please help Thx
Hi. I believe you don’t have the same code, otherwise you wouldn’t have that error. By reading your error, I could say that you didn’t register the RepositoryContext class. You can always download our code and compare it with yours.
Hello guys, this article has so solid content that I always come back to clarify some things.
I have a question regarding
AddRange/UpdateRange
method which I believe its the below solution.Is it good practice to use inside a new
CreateRange/UpdateRange
method in order to save collection of models or is there a better way.Also do you have any Idea what is happening to AddOrUpdate method from EF Core. I need to create an Upsert method to the User Repositories.
Hello Jurgen. If you have a collection of entities that you want to save or to update to db it is always a good solution to use AddRange or UpdateRange, it works the same for the RemoveRange part. You are not actually saving or updating anything from db by calling those methods you are just modifying the State property of all the entities. EF Core uses TrackChanges to track all the entity changes for the given context and based on that once you call SaveChanges it know what to do in db.
So this is basically answer to your second question. All the entities has the state property and it can be Detached, Added, Unchanged, Modified, Deleted. So if you use the Add method you are setting the state of that entity to Added. Once you call the SaveChanges it will look at the State property and figure it out what to do.
Hope this clears it up for you.
All the best.
Great, thank you for explaining the states it will take me like 2-3 hours to understand what is happening.
So what I read on Update method from EFCORE method summary is
In other words If on the Map() method I pass everything needed apart from the primary key and let the GetOwnerById() (which is called before Map()) function do it’s job. Then Update is enough for me.
You are correct. By calling the GetOwnerById method you will return the Owner object from the database with its id. Then when you do the mapping and call the update it will add the state Modified and will update the entity in the db. If you want to go dipper into the EF Core logic, you would see that when you change any property of the tracked entity it will get the Modified state and by just calling the SaveChanges, without Update, it will modify the entity in the database. I am calling update here because I am using RepositoryPattern with AsNoTracking() method, which detach the entity from the tracking graph, thus making queries faster. But again, that is more EF Core related and we are going to have series about EF Core soon enough. There are many good things to learn about EF Core under the hub 😀 All the best.
Thank you for the comments Marinko. I really appreciate it.
hmmm… What if I change ORM (like it will ever happen 😛 ). Shouldn’t it be better to use Add ELSE Update just for re-usability purpose?
You must use Add if you want to insert entity to db. About update, if you know which properties are modified than you usually don’t need Update method, if don’t then you must use it (it will set all the properties to modified).
Hi , Team ,
I am not able to run the project. it says 404 error. I am using .net core 2.1
Hello Deepak. We need more details about your issue, what is your launchSettings configuration, how do you start your app, when do you get 404 etc… My suggestion is always to download our project and check for differences.
Hi Marinko, I am implementing a new project with this pattern, but I have some questions more.
– Where do you advise me to implement stored procedures? in the Repositories or BaseRepository.
– If I have several system modules is there any disadvantage separating in various project repositories and using the same RepositoryContex?
Thank you.
Hello Marcial. Regarding the stored procedures, I believe you are asking me where to implement a logic to call a stored procedure from your DB and my answer is in the Repository class, because you need to use a raw query to call that procedure. I think there is no place for a raw query inside a BaseRepository class which is completely generic.
Regarding the second question, I will always recommend to split your entire project into smaller ones if there is need to it, but there is no need to share repository logic across projects. Keep the Repo logic inside a single project and then just reuse its functionality. At least, that is how I would do it.
All the best.
Hi guys,I made my repository following this tutorial ( great tutorial!), but I find it hard to implement Memory cache using decorator pattern 😕 can you give me a hint or even more info 😀 how to implement it 😕 thank you
Using this tut for cache https://ardalis.com/building-a-cachedrepository-in-aspnet-core
And I kinda got lost between both of tuts 🙁
Hello IK. Well as much as I could see it what you need is the decorator class which will accept two parameters through the constructor: the repository class and the IMemoryCache interface. Then all you need to do is to call that cache method with the GetOrCreate call. Finally you must register this new Cached service in your IOC if you are using .NetCore as the Steve did. It is quite usual implementation of the Decorator pattern. Again, I haven’t tried to implement this cache or anything like it, just telling you my conclusion based on a quick look.
Thanks for your article which helped me a lot to better understanding .net core in real projects. I still have a question that how to apply this pattern for many-to-many db entities? in framework core, this is the only way to define m-m relationship:
“`
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//many-to-many
modelBuilder.Entity().HasKey(ea => new { ea.ExperimentId, ea.ApparatusId });
modelBuilder.Entity().HasKey(er => new { er.ExperimentId, er.ReagentId });
}
“`
as ExperimentApparatus and ExperimentReagent were not added to DbSet, How can i retrieve them in repository?
Hello Roy. First of all Thunder is just a reader who made a first comment a year ago, so I believe he is not going to reply 🙂
So, for many to many relations you would do the same as you did untill now. You would have repo class for each entity and combine them as you needed. Just to say, this is an easy, and not so complex example, only two entities, thus the repo wrapper injected in the controller. But with the additional complexity, as it would be with additional tables, you should have an additional layer for the business logic, and repo wrapper would be injected in there. All the best.
Thanks for such a great article. I have doubt in unit testing.
I tried to do unit testing for this but since our controller is dependent on wrapper instance in constructor, when I am creating a mock of Account using IRepositoryBaseService in my test project, how can I inject this in ControllerTest. I am using approach mentioned here for unit testing: http://34.65.74.140/unit-testing-aspnetcore-web-api/
Hello.
Could you try to also create mock version of RepositoryWrapper, using IRepositoryWrapper interface. Then you could inject IRepositoryWrapper into you controller constructor.
You would have to setup the mock RepositoryWrapper instance to return mock version of Account repository when Account property is called on RepositoryWrapper dough.
Anyhow, we are creating a demo test for this repository + controller logic, so we are going to share that code with you. We are sure that that is going to help not only you but all the other readers as well.
All the best.
Thanks for replying. I’ll try this approach btw may I know when are you planing to release demo + test app?
Soon. We are working on it as we speek.
Here are the link of the source code. We have been using the Moq library (which was mentioned in the Unit Test article). https://gist.github.com/vladimir-pecanac-main/f89a4a967b4433f2796163169b1fc959
All the best.
Hi Marinko,
In below line
ownerRepoMock.Setup(x => x.GetOwnerById(existingGuid))
.Returns(new Owner()
{
Id = existingGuid,
Address = “test address”,
Name = “test name”,
DateOfBirth = DateTime.Now
});
you are calling ownerRepoMock but in our case we will be invoking Setup(x => x.FindByCondition(y => y.Id == exitingId)). will this make any changes?
As after mocking I am not able to persist above created test entity to my controller.
Hello. Well you don’t need to write tests for the Repository logic, the FIndByCondition method is a pure EF functionality, why would you test that. It would be as if you want to test if Entity Framework works as it supposed to, and we all know that it does 😀 So, what you need to test is your controller and your actions, this is the place where you return your results to the presentation layer and this is something you want to test.
Hi @@disqus_GtEeIZUUDN:disqus
I’ve got one question. With respect to the example above, let’s say that you had only one repository which is AccountRepository. How to get all owners inside the account repository?
The reason I ask this is because I’ve JobRepository and I want to get all JobTypes. I’m thinking JobType shouldn’t have its own repository and should be in JobRepository.
Hello Hussain. If you read the next article from this series, you will see how to get all the accounts per single owner inside the owner repository file. In the same way you can get all the accounts in the owner repo file or all the owners in the accounts repo file. So you could write something like this: RepositoryContext.Owners.ToList(), to fetch all the owners inside the Account repo file.
Thanks @disqus_GtEeIZUUDN:disqus. Since I missed that, I guess it’s time for me to sleep. Thanks again.
Hello Marinko,
Can I have your opinion for the following question?
Fluent API or Data Annotations?
Hello Jurgen. From my perspective, the Data Annotations approach is better to setup constrains on your models (required, StringLenth…) because as soon as you look at your model you can see what restrictions it has. Yes it would add additional lines to the class but it is still easy readable. For everything else, any type of EF configuratin, data seed, lazy loading setup etc I would use Fluen API approach. Especially for the data seed. In EF Core by using ApplyConfiguration method, you can separate your seeding logic from the OnModelCreating class, thus making that class more readable as well.
How about using Automapper to map from entity class to extended models(dtos)
This is always a good idea. But as you can see our objects are not that big, so we are loosing nothing by mapping them manually. Still, we always encourage AutoMapper usage.
Hello guys, how this repository pattern can be replicated for MongoDB? By the way have you tried MongoDB.Driver
Hello Jurgen. Well unfortunately we didn’t use the MongoDB driver with .NET Core. So we are not able to help you with your question, sorry for that.
So unlucky… I love your pattern so far, especially the wrapper idea which replicates the UOW pattern. Are your guy making a microservices API tutorial?
We haven’t planned it yet. But it is on our list 😀
Hi Marinko,
Thanks for the great tutorial, I’ve learnt a huge amount from it already.
I was just wondering what would be involved in adding eager loading to the repository pattern? I’m guessing a .Include method would needed to be added to the IRepositoryBase and RepositoryBase?
thanks for the article. can i use ThenInclude with this generic repository?
You are very welcome. If you want to use ThenInclude or Include, you would have to add the navigation properties for the Owner and Account models. I believe it won’t work otherwise. Of course you need to include the using directives from EF Core to be able to use Include or ThenInclude.
I hope this helps. All the best.
I can use include with my generic repository but could not figure out how to implement theninclude
https://gist.github.com/ucanbaklava/5f670697e500f5bf1be711d20e912dee
I’ve rarely seen such a good tutorial.
However, how do you manage nested object ? Let’s say I have an object A, which contains a list of B, and every B contains one or multiple C.
I guess we should go with lazy loading right ? Would be nice to have a solution in the tutorial 🙂
Hello Shirouste. First of all thank you so much for reading this tutorial and leaving kind words and your suggestions. About your suggestion it completely makes sense, and you have a great point on that. Even though it could be done without lazy loading, it is good for readers to know about it. But, we already have so much information in this article and adding additional info could make this article more complicated and this is not our goal. We want everyone to have a chance to understand it. But if you do a little search through our blog, you will find articles that talks exactly about the thing you have required. So for the DB-First approach we have this: http://34.65.74.140/asp-net-core-web-api-with-ef-core-db-first-approach and in there you can read more about eager loading, lazy loading etc. And if someone wants to read about the CodeFirst Approach he/she can read it here: http://34.65.74.140/net-core-web-api-ef-core-code-first/ . I believe you get my point. Again, you are completely right with your suggestion, but we need to spread a topics a bit 😀 One more time, thank you very much for your suggestion.
That was fast ! Thanks for your reply
Hi Marinko. First of all thanks for great posts and I already learned new things. Anyway, when we add anything in Startup.cs (ConfigureServices method) it’s added above call to services.AddMvc. Any reason why?
Hello Mursel. Thank you for your comment and for reading our articles. I am very glad to hear that they are helpful to you. About your question, there is no any special reason for that. Just the AddMvc() method is registering many default services required for the app to work, so I prefer to keep that as a final action. You will find in many articles (even on Microsoft ones) examples where they register they own services after the AddMvc method.
Thanks for clarification. Best regards!
Hi @disqus_GtEeIZUUDN:disqus, thanks for this great series, it’s really helpful and easy to follow. I’ve got one question.
Let’s say you have a User table and an Employee table that references User table (one-to-one relationship)
So, we will create one repository for User and another for Employee.
Now, when you create an employee, you want to create the user before as the employee depends on it’s primary key.
So when user hits the EmployeeController with the Employee object, we will need to save employee.User first then employee.
What is the best way to do this?
Hello Hussain. If you have two tables with 1:1 relationship, I would suggest to move them all to just one table. Because in great majority of cases 1:1 relationship means that those two tables should be only one table. And this would solve your current problem. But if you still want to have this type of table separation, then you can read our article http://34.65.74.140/asp-net-core-web-api-with-ef-core-db-first-approach/ . In there you can read more about adding connected entities to the data base as soon as you add the main entity.
Thanks Marinko, you’ve been very helpful. Best Regards, and keep up the good work.
Showing following issue even installing EntityFrameworkCore https://uploads.disquscdn.com/images/7e307b49bcf8b848c409544a6b71a049aff42aebf3e56f15686af5ab47cb8a1d.png
Hello Vipin. Please note that you are missing T in IRepositoryBase signature, it should be public interface IRepositoryBase< T>. Your error is not related to the EF Core.
I think you forgot to dispose of the repo context in RespositoryBase. Then you could use that method in your controllers’ override Dispose method. But since you’re not using UOW pattern, you’d have to dispose of it like _repoWrapper.Owner.Dispose()
Hello mate. Well I don’t have to dispose it, at least not for the .NET Core’s environment. Since the Context class is registered in the IOC with the AddDbContext method (and by default it is registered as Scoped lifetime – per request ) the dbContext is going to be disposed as soon as lifetime expires, or in this case, as soon as your request is finished.
I even tried to dispose it manually (when I was starting with .NET Core) but the framework trowed me an error in which it states that I shouldn’t be disposing anything it will take care of it for me.
Hi Marinko,
First of all, I want to thank you for this great tutorial series, I am learning so much from it.
I have a question/comment which is a bit general on the architecture here, coming from my interpretation of “separation of concerns”:
Isn’t it a bit weird that your Contracts projects references the Entities projects?
The way I see it, it’s Contracts which should be referenced in Entities, and provide the interfaces IOwner and IAccount to implement in the model.
That way, your controllers wouldn’t directly depend on the model… I thought the point of the Contracts projects was to provide contracts between the different projects here.
Maybe the advantage would not be so much visible in your example, but I put in a little extra effort to adapt it to my own model, which consists of two tables in a many-to-many relationship (between Project and Fish… don’t ask^^). There, I had to add some technical code and properties both in the model and the repository to make it work (since EF core doesn’t directly support many-to-many relationship mapping).
My point is: these additional properties (which only concern the very-back-end) are now visible from the controllers, and it becomes a bit confusing and blurry… so I decoupled using IProject and IFish, so the controller doesn’t consume the model directly.
Does this make sense to you?
Hello Nicole. Thank you for reading our articles and for your comment as well. If I understood you correctly, than what you did makes perfect sense to me. I didn’t want to go that deep into the implementation, but creating an IOwner and IAccount interface for the Owner and Account models to implement to, is a good solution. Because then we wouldn’t have to inject Owner class and Account class into the Contracts project thus removing that reference towards the Entities project. Also IEntity should be readdressed.
Thank you for your suggestion, its a great one.
Hey, excellent serie of articles, it helps me a lot on my Web Api project.();)
Three questions:
1) I can’t seems to see where concrete RepositoryContext its actually created because you always use it with its interface IRepositoryWrapper (suppose its something to do with the services.AddScoped
2) Why don’t you instance the context inside the RepositoryWrapper? (you created outside and pass it as constructor parameter)
3) If I need to query multiple databases, how can I pass connection string to RepositoryContext?
Thanks again!
Hello Eric. Thank you so much on your kind words, I really appreciate it. Let me answer your questions:
1) RepositoryWrapper is just a class to wrap your customer repositories (Owner, Account, or any other table you want to include). The RepositoryContext class is included with this code:
var connectionString = config[“mysqlconnection:connectionString”];(o => o.UseMySql(connectionString));
services.AddDbContext
2) You don’t have to instantiate RepositoryContext class. With the code above, you have registered it inside the IOC and now you can include it in any class by providing its object in the constructor. That’s the main advantage of the IOC and DI, not only in .NET Core but in .NET overall if you implement IOC support (just in .NET Core it is implemented by default).
3) If you need multiple databases it is best to create separate Context classes for each of them and than just to include the one you need inside any constructor you want. But if you want just to split your connection strings between development and production environment, you can have one context class but you must use environment object in .NET Core to provide information about your current environment:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
//register context with development connection
}
else
{
//register context with different connection string.
}
}
Hope my answers helped you.
All the best.
Thank you Marinko! The problem with my project is that I can define all connection string because databases can be dynamic, added. That’s why I need to pass connection string to the constructor of the context.
Hi Marinko Spasojevic ,first of all thanks for such a great post.I am new in .net Core.
I have an error in the RepositoryBase.cs class.
public IEnumerable FindAll() ();
{
return this.RepositoryContext.Set
}
And
public void Save()
{
this.RepositoryContext.SaveChanges();
}
Error CS1061 ‘RepositoryContext’ does not contain a definition for ‘Set’ and no accessible extension method ‘Set’ accepting a first argument of type ‘RepositoryContext’ has been located (a using directive or an assembly reference is- it’s missing?) Repository D: code WebAppProthese Repository RepositoryBase.cs
And
Error CS1061 ‘RepositoryContext’ does not contain a definition for ‘SaveChanges’ and no ‘SaveChanges’ accessible extension method that accepts a first argument of type ‘RepositoryContext’ has been located (a using directive or an assembly reference is- it’s missing?) Repository D: code WebAppProthese Repository RepositoryBase.cs
Thnx
Hello Mohsen. Have you installed EntityFrameworkCore in your project. In this article you have a solution, right before creating the RepositoryBase class, how to reference EFCore in your new project. Or if you don’t want to do it like that, you can simply install it via NuGet Package Manager.
If this don’t solve your problem, you can upload your project on GitHub and I will look at it to see if I can find the problem.
All the best.
Hello Marinko. Thank you for your response. first i am new in .net it is my first project (but i am devolopper PHP).
I have already installed Pamelo.EntityFramworkCor.MySql (2.1.1) in my main project via NuGet Package Manager.And i alos have installed EntityFrameworkCore.
Hi mate. Sorry for this late response, I have seen yours just now, don’t know why google didn’t notify me. But let me explain to you. You have installed Pomelo and EF Core, but you did it in your main project. But, you have Repository project as well (if you are going along with my tutorial) and in there you need to have EF Core as well. I have explained in this post how to reference EF Core in a new project or if it is easier for you, just install it in that project again. Can you do that, and then reply if it works?
Thank you Marion.
Yes i already install EF Core in my Repository project.
My project in this adress https://github.com/ghanmy/WebAppProthese.
Can you please show what is the bug?
Best regards
Ok mate, I don’t have permission to commit to your branch so let me explain in here:
1)In your WebAppProthese project, you have MySql package installed. You don’t need that, so remove it and install Pomelo.EntityFrameworkCore.MySql. By doing this, the UseMySql extension method wont report an error.
2) In your Entities project you had the DbContext, DbContextOption and DbSet classes, that you have created on your own. You don’t have to do that. Just remove all of these classes. They are provided by EFCore.
3) In your WebAppProghese project, you have the RepositoryContext class. This is not required. You already have that class in your Entities project. So, delete this class from the WebAppProthese project and just add using Entities statement in your ServiceExtensions class, to use the class from the Entities project.
After all of these changes, your project builds without errors.
All the best.
thank you , you are the best 🙂
Hi Marinko, thank you for this excellent tutorial, I’ve followed it and loved the overall design of the application and the use of DI and IOC. I wanted to know, as someone relatively new to this way of developing, how would you go about creating a method to return only the Owner names? Think of a scenario where you’re wanting to put the names in a list, would you want to select all the entities or the single columns? Forgive me if this is a silly question, I’m still thinking along the lines of SQL views and queries…
Hello Daniel. Thank you for reading our posts and for your kind words.
There is several ways to extract only names or any property from the list but let me explain just one 😀 As you can see, we have FindAll() generic method in our RepositoryBase class. So what you can do is to create a new method inside the OwnerRepository class (this class is introduced in the next article) and inside you can write method that calls FindAll().Select(own => own.Name).ToList(); Or if you want to keep only IEnumerable than just don’t call ToList() method. So as you can see, this is just a simple LINQ query, nothing more than that.
And I want to tell you, there is no silly questions and I have none to forgive you. I write this articles so I could help readers and answer the comments for the same point. If this reply helps you, than I am satisfied for sure 😀 So just keep on working and asking questions all over the internet 😀
Thank you so much Marinko!! I really appreciate you taking the time to reply to a comment on such an old post! I really like your approach, if I’m not mistaken, your approach looks very similar to what I saw on a tutorial on C# Design Patterns. What would you recommend I do to learn, not only the Entity Core framework but the overall approach that you’ve taken when building this project? I come from a Win/Web Forms background and this approach is very new to me
Hi Daniel, let me try to summarize the learning curve for you, even though no one can tell you exactly in which order to learn something. But, I will tell you my path.
As I can read, you came from Win/Web Forms, so (if you haven’t used the Visual Basic) I assume you are good at C# and OOP. But if you are just good in OOP, I suggest to dive even more in the object oriented concepts, this is so important. I have started with Win/Web Forms as well, but after that continued to the MVC projects. While learning about MVC, I have learnd about Entity Framework and LINQ as well. Then, I started learning about .NET Core Web API and EF Core. After all of that, I transfered my self to the client side a bit, by learning Angular and React. If you go through our entire .NET Core series and then through entire Angular or React series, you will see that all of the mentioned above has been implemented.
So, there you go. The main thing is that you are hungry for knowledge and to never stop learning. Just keep writing code, make mistakes, fix that mistakes and learn more 😀
Hi Marinko, thank you for the advice, I think I need to spend more time on MVC & Entity Framework as well as looking at design patterns.
Thanks again for creating this tutorial and taking the time to respond!
Hi, Maybe a newbie question but why create a new project for the models, why not create a model folder in the main project, what problem does this solve?
Hello ddarkeh x. First of all, thank you for reading this article. Second of all, there are no newbie questions. All the questions are valid and the answer on that question may help not only the person who ask that question, but to someone else as well. So, to answer it… I like to separate my projects as much as I can due to re-usability purpose. Imagine if you have to start working on another project, you will have a different business logic but maybe (for any reason) you need the same database. Well you can just inject this Entity project into your new project and continue to work without creating your models and context classes etc… So, this is the main reason. The other one is that the project is much readable and easier to search through if it doesn’t have a lot of folders inside (but this is personal opinion).
I hope, this answer clears your doubts.
All the best.
Hi Marinko,
Thanks for providing this article. I have followed all the steps mentioned in the article. I just used DB first approach to create the classes in the database classes using command for scafolding. One more thing I have creted seprate library for models and generic repository and for interface. Then one seprate library service for implementing my indivisuals classes of interface and repository.
Now i am facing error is datacontext object =null everytime how can i resolve this issue? please help me to resolve issue.
Thanks in advance.
Omkar.
Hello Omkar. Thank you for reading this article. I am going to try to help you, but I am not sure about all the things you did. So my first question did you registered your RepositoryContext class inside services IOC. This code: services.ConfigureMySqlContext(Configuration); and of course did you properly configured the method ConfigureMySqlContext? If you did this well, then my second question is: Did you provided an repositoryContext object inside the RepositoryWrapper constructor:
public RepositoryWrapper(RepositoryContext repositoryContext)
{
_repoContext = repositoryContext;
}
If you haven’t done this, your datacontext will be null for sure.
If none of this helps, maybe to share your code, so I could look at it better.
All the best.
Hi Marinko,
Thanks for quick help. Below code resolve my problem.
public RepositoryWrapper(RepositoryContext repositoryContext)
{
_repoContext = repositoryContext;
}
Now I am facing one more problem, Can you help me in this for resolve this issue.
SqlException: Login failed for user ”. I am using windows authentication mode for sel server. Be;ow is my connection string.
Data Source=mypcuser\SQLEXPRESS;Initial Catalog=SimpleDemoApp;Integrated Security=True
Thanks in advance.
Omkar.
Have you maybe tried to use Server instead of Data Source, or to create connection string like this: “Server=.;Initial Catalog=SimpleDemoApp;Integrated Security=True”. Or try to read the connection strings on the internet, you can find a different variations, maybe some of them can help you.
Yes thanks Marinko,
I have updated the connection string now it’s working fine. Can you help me for implementing automapper in code. Just give me idea where can I put code for mapping I will try to integrate in code.
Thanks once again.
Omkar.
DbContext/DbSet is already an implementation of the repository/UoW patterns, any reason behind making your own?
Hello Matthiee. We are aware of DbContext/DbSet implementation. The purpose of this article is to show how we can create repository in the .NET Core Web API. It fits perfectly for this type of project. I wouldn’t go into why is it good or bad, there are tons of articles all over the internet about that topic.
Hi Marinko Spasojevic, thanks for a post. But I confused about your RepositoryContext class. Where can I register the deependency to construtor to RepositoryWrapper class or it will be automatic understand ?
Hello Hieu. Thank you so much for reading the post and for commenting as well.
To answer on your question: You need to register the RepositoryContext class first in order to use it in the RepositoryWrapper class.
So let me just quick guide you through the process:
We have registered the RepositoryContext clas inside the Startup class in the ConfigureServices method : services.ConfigureMySqlContext(Configuration); .
ConfigureMySqlContext is an extension method in which we register our RepositoryContext class as a service: services.AddDbContext(o => o.UseMySql(connectionString));
By doing that, we have placed the RepositoryContext class inside the IoC container. Now we can use it with a construction injection (that is how Dependency Injection works) in every class we want.
I hope, you have better understanding of this process now.
All the best.
Hi Marinko Spasojevic ,first of all thanks for such a great post.I tried to implement your pattern in my project but i have used Microsofts SQL database,but i end up getting exception at last “There is already an open DataReader associated with this Command which must be closed first.”.if u have any clue then fine or else
Hello Gaurav Dubey. Thank you very much for reading the post. About your error. It is really hard for me to say what is the problem, because I don’t know how did you implemented your db context. But I have searched a bit over the net and found out that problem could be caused by lazy loading triggered when iterating over the results of some query. This can be easily solved by allowing MARS in your connection string. Add MultipleActiveResultSets=true to the provider part of your connection string (where Data Source, Initial Catalog, etc. are specified).
I am not sure if this can solve your problem but it is worth trying.
Another solution is to try to implement complete repository as I did in this project. It is not too different from using the MySQL db, just you don’t need to install Pomelo library and instead of services.AddDbContext(o => o.UseMySql(connectionString)); you can write
services.AddDbContext(o => o.UseSqlServer(connectionString));
Again Big thanks Marinko, look at my connection string
“connectionstring”: “Data Source=myserver;Initial Catalog=MyDatabase;Integrated Security=SSPI;MultipleActiveResultSets=True”
by applying mars it worked.
prior to this i was using this format of connection string=====>
“Server=(localdb)mssqllocaldb;Database=Blogging;Trusted_Connection=True”
which is given on microsofts website and it never worked in my case.
You are very welcome Gaurav. Again thank you for reading the post. I am glad that content from this post also helped you in your code.