DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • MongoDB to Couchbase for Developers, Part 1: Architecture
  • Introduction to Couchbase for Oracle Developers and Experts: Part 4: Data Modeling
  • What Java Developers Need to Know About Geo-Distributed Databases
  • Introduction to Couchbase for Oracle Developers and Experts: Part 2 - Database Objects

Trending

  • Build Your First AI Model in Python: A Beginner's Guide (1 of 3)
  • How to Build Local LLM RAG Apps With Ollama, DeepSeek-R1, and SingleStore
  • Scalable, Resilient Data Orchestration: The Power of Intelligent Systems
  • Stateless vs Stateful Stream Processing With Kafka Streams and Apache Flink
  1. DZone
  2. Data Engineering
  3. Databases
  4. Implementing the Repository Pattern Using C# and Entity Developer in ASP.NET Core

Implementing the Repository Pattern Using C# and Entity Developer in ASP.NET Core

In this article, take a look at implementing the repository pattern using C# and Entity Developer in ASP.NET Core.

By 
Joydip Kanjilal user avatar
Joydip Kanjilal
DZone Core CORE ·
Sep. 11, 20 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
26.9K Views

Join the DZone community and get the full member experience.

Join For Free

Introduction

The Repository Pattern is one of the most popular design patterns used for abstracting how data is eventually persisted in the database or retrieved from the database. The basic objective of the Repository Pattern is to help you decouple the data access and business logic layers of an application. This article talks about how we can implement the repository pattern in C# and take advantage of Entity Developer to talk to the database.

Why Should We Use an ORM?

An ORM is an acronym for Object Relational Mapper - it is used to map your domain objects to the objects in the relational model. In other words, it is used to map data between incompatible type systems. Entity Developer from Devart is an ORM designer tool that lets you design your data access layer visually. It sits on top of ADO.NET and simplifies the way you work with data.

Entity Developer supports ADO.NET Entity Framework, Entity Framework Core, Hibernate, LinqConnect, Telerik Data Access, and LINQ to SQL. You can download a copy of Entity Developer and get started.

Prerequisites 

To be able to work with the code examples demonstrated in this article, you should have the following installed in your system:

  • Visual Studio 2019 Community Edition
  • SQL Server 2019 Developer Edition
  • Entity Developer

You can download Visual Studio 2019 from here: https://visualstudio.microsoft.com/downloads/

You can download SQL Server 2019 Developer Edition from here: https://www.microsoft.com/en-us/sql-server/sql-server-downloads

You can download a copy of Entity Developer (trial version) from here: https://www.devart.com/entitydeveloper/download.html

Create the Database

Now that the ASP.NET Core Web API project has been created in Visual Studio 2019; the next step is to create the database. Note that for the sake of simplicity we’ll use a database with just two tables with simple design in this example.

Launch the SQL Server Management Studio and create a new database called Demo. Next, use the following script to create two tables named Products and Categories inside the Demo database.

SQL
 




xxxxxxxxxx
1
51


 
1
CREATE TABLE [dbo].[Products](
2

          
3
      [ID] [int] IDENTITY(1,1) NOT NULL,
4

          
5
      [ProductName] [nvarchar](40) NOT NULL,
6

          
7
      [CategoryID] [int] NOT NULL,
8

          
9
      [QuantityPerUnit] [nvarchar](20) NULL,
10

          
11
      [UnitPrice] [money] NULL,
12

          
13
      [UnitsInStock] [smallint] NULL,
14

          
15
      [ReorderLevel] [smallint] NULL,
16

          
17
      [Discontinued] [bit] NOT NULL,
18

          
19
 CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED 
20

          
21
(
22

          
23
      [ID] ASC
24

          
25
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
26

          
27
) ON [PRIMARY]
28

          
29
GO
30

          
31
 
32

          
33
CREATE TABLE [dbo].[Categories](
34

          
35
      [ID] [int] IDENTITY(1,1) NOT NULL,
36

          
37
      [CategoryName] [nvarchar](15) NOT NULL,
38

          
39
      [Description] [ntext] NULL,
40

          
41
 CONSTRAINT [PK_Categories] PRIMARY KEY CLUSTERED 
42

          
43
(
44

          
45
      [ID] ASC
46

          
47
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
48

          
49
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
50

          
51
GO



Figure 1 shows how these two tables are related.

article image


We’ll use this database in the subsequent sections of this article to store, edit, delete, and retrieve data.

Create a New ASP.NET Core Web API Project

Assuming that the necessary software has been installed in your computer to be able to work with Entity Developer, follow the steps outlined below to create a new ASP.NET Core Web API project.

  1. First off, open the Visual Studio 2019 IDE
  2. Next, click "Create a new project" once the IDE has loaded
  3. Click "Create a new project"
  4. Next, select "ASP.NET Core Web Application"
  5. Click the "Next" button
  6. Specify the project name and location - where it should be stored in your system
  7. Optionally, click the "Place solution and project in the same directory" checkbox.
  8. Next, click the "Create" button
  9. In the "Create a new ASP.NET Core Web Application" dialog window that is shown next, select "API" as the project template.
  10. Select ASP.NET Core 3.1 or later as the version.
  11. You should disable the "Configure for HTTPS" and "Enable Docker Support" options by disabling the respective checkboxes.
  12. Since we'll not be using authentication in this example, specify authentication as "No Authentication".
  13. Finally, click on the "Create" button to finish the process.

Create an Entity Data Model

The next thing you should do is create an entity data model. When you create a model in Entity Developer, there are two options to choose from: Database First (this is selected by default) and Model First. In this example, we’ll take advantage of the Database First approach. Remember to select the “Generate from Database” option to generate your model from the database and select the database objects you would want to be a part of your entity data model.

Follow these steps outlined below to create an entity data model in Entity Developer using the database-first approach.

1. Select your project in the Solution Explorer Window

2. Right-click and select Add->New Item

3. Select Devart EF Core Model as the template as shown in Figure 2

article image

4. Specify a name for your entity data model and click Add

5. Specify the connection properties and test the connection

6. Click on the “Next” button to continue.

7. By default, the option “Generate from Database” will be selected. Since we want the model to be created from the database, click on the “Next” button to continue.

8. De-select all options and then specify only the database objects you would like to be a part of the model. Here’s where you should select the Products and Categories tables.

9. In the "Set up naming rules" screen you can optionally specify naming rules for your entities.

10. In the next screen, you can optionally specify the model properties.

11. In the next screen, you can optionally choose the model diagram content.

12. In the next screen, you can optionally specify code generation templates.

13. Specify Repository and Unit of Work as the code generation template as shown in Figure 3.

article image

14. Lastly, click “Finish” to complete the process.

Your ADO.NET Entity Data Model using Entity Developer will be created along with the repository and unit of work classes and interfaces. Here’s how your Entity Data Model would look like.


article image

Generated Classes and Interfaces

Here’s how the Solution Explorer Window would look like – note the generated classes and interfaces.


article image


If you observe the generated classes and interfaces in the Solution Explorer Window, you'll find three repository interfaces namely IRepository, IProductRepository, and ICategoryRepository, and three repository classes namely EntityFrameworkRepository, ProductRepository, and CategoryRepository. You'll also observe the Category and Product classes - these are model classes. You'll also observe the IUnitOfWork interface and the EntityFrameworkUnitOfWork and EntityFrameworkUnitOfWorkFactory classes - these are types used for using the unit of work design pattern. In the sections that follow we’ll examine how we can work with these classes and interfaces.

Using the Repository Classes and Interfaces

There are two approaches to building repositories in an application. These include the following: -

  • Repository per entity type
  • Generic Repository

The easiest approach to implementing the Repository design pattern is to create a repository per business object. The generated repository we used earlier follows this approach. Since we've two tables, there are two business classes namely Product and Category, and you would typically have two classes named ProductRepository and CategoryRepository implementing two interfaces IProductRepository and ICategoryRepository respectively.

The following code snippet shows the IRepository, IProductRepository and ICategoryRepository interfaces.

Java
 




xxxxxxxxxx
1
33


 
1
public partial interface IRepository<T>
2

          
3
    {
4

          
5
        void Add(T entity);
6

          
7
        void Remove(T entity);
8

          
9
    }
10

          
11
 
12

          
13
public partial interface IProductRepository : IRepository<Product>
14

          
15
    {
16

          
17
        ICollection<Product> GetAll();
18

          
19
        Product GetByKey(int _ID);
20

          
21
    }
22

          
23
 
24

          
25
public partial interface ICategoryRepository : IRepository<Category>
26

          
27
    {
28

          
29
        ICollection<Category> GetAll();
30

          
31
        Category GetByKey(int _ID);
32

          
33
    }



The EntityFrameworkRepository class represents a generic repository and implements the IRepository interface. The ProductRepository class implements the methods declared in the IProductRepository interface and the CategoryRepository class implements the ICategoryRepository interface. Please find these classes below.

Java
 




xxxxxxxxxx
1
189


 
1
public partial class EntityFrameworkRepository<T> : IRepository<T> where T : class
2

          
3
 {
4

          
5
        private DbContext context;
6

          
7
        protected DbSet<T> objectSet;
8

          
9
 
10

          
11
        public EntityFrameworkRepository(DbContext context)
12

          
13
        {
14

          
15
 
16

          
17
            if (context == null)
18

          
19
            {
20

          
21
                throw new ArgumentNullException("context");
22

          
23
            }
24

          
25
 
26

          
27
            this.context = context;
28

          
29
            this.objectSet = context.Set<T>();
30

          
31
        }
32

          
33
 
34

          
35
        public virtual void Add(T entity)
36

          
37
        {
38

          
39
 
40

          
41
            if (entity == null)
42

          
43
            {
44

          
45
                throw new ArgumentNullException("entity");
46

          
47
            }
48

          
49
            objectSet.Add(entity);
50

          
51
        }
52

          
53
 
54

          
55
        public virtual void Remove(T entity)
56

          
57
        {
58

          
59
 
60

          
61
            if (entity == null)
62

          
63
            {
64

          
65
                throw new ArgumentNullException("entity");
66

          
67
            }
68

          
69
            objectSet.Remove(entity);
70

          
71
        }
72

          
73
 
74

          
75
        public DbContext Context 
76

          
77
        {
78

          
79
            get 
80

          
81
            {
82

          
83
                return context;
84

          
85
            }
86

          
87
        }
88

          
89
 }
90

          
91
 
92

          
93
 public partial class ProductRepository : EntityFrameworkRepository<Product>, IProductRepository
94

          
95
    {
96

          
97
        public ProductRepository(DemoModel context) : base(context)
98

          
99
        {
100

          
101
        }
102

          
103
 
104

          
105
        public virtual ICollection<Product> GetAll()
106

          
107
        {
108

          
109
            return objectSet.ToList();
110

          
111
        }
112

          
113
 
114

          
115
        public virtual Product GetByKey(int _ID)
116

          
117
        {
118

          
119
            return objectSet.SingleOrDefault(e => e.ID == _ID);
120

          
121
        }
122

          
123
 
124

          
125
        public new DemoModel Context 
126

          
127
        {
128

          
129
            get 
130

          
131
            {
132

          
133
                return (DemoModel)base.Context;
134

          
135
            }
136

          
137
        }
138

          
139
    }
140

          
141
 
142

          
143
public partial class CategoryRepository : EntityFrameworkRepository<Category>, ICategoryRepository
144

          
145
    {
146

          
147
        public CategoryRepository(DemoModel context) : base(context)
148

          
149
        {
150

          
151
        }
152

          
153
 
154

          
155
        public virtual ICollection<Category> GetAll()
156

          
157
        {
158

          
159
            return objectSet.ToList();
160

          
161
        }
162

          
163
 
164

          
165
        public virtual Category GetByKey(int _ID)
166

          
167
        {
168

          
169
            return objectSet.SingleOrDefault(e => e.ID == _ID);
170

          
171
        }
172

          
173
 
174

          
175
        public new DemoModel Context 
176

          
177
        {
178

          
179
            get 
180

          
181
            {
182

          
183
                return (DemoModel)base.Context;
184

          
185
            }
186

          
187
        }
188

          
189
    }



You can now take advantage of dependency injection to inject these instances to your controllers. The following code snippet illustrates how you can create instance of the product repository in the ConfigureServices method of the Startup class.

Java
 




xxxxxxxxxx
1
11


 
1
public void ConfigureServices(IServiceCollection services)
2

          
3
{
4

          
5
    services.AddScoped<ProductRepository>(x =>
6

          
7
    { return new ProductRepository(new DemoModel()); });
8

          
9
    services.AddControllers();
10

          
11
}



Use the Repository in the Controller Classes

Now that we’ve the repository class ready, let’s create controller classes and examine how we can use these repositories in them. Follow the steps given below to create the Product and Category controller classes in your project.

  1. Select the project in the SolutionExplorer Window
  2. Right-click and click on Add->New Item…
  3. Select the “API Controller with read/write actions” template
  4. Specify a name for your controller class
  5. Click Add to add the new controller to your project

To use the repository instances, we should take advantage of dependency injection to inject an instance of the ProductRepository class as shown in the code snippet given below.

Java
 




xxxxxxxxxx
1
23


 
1
public class ProductController : ControllerBase
2

          
3
{
4

          
5
   private readonly IProductRepository _productRepository;
6

          
7
 
8

          
9
   public ProductController(IProductRepository 
10

          
11
                             productRepository)
12

          
13
   {
14

          
15
     _productRepository = productRepository;
16

          
17
   }
18

          
19
 
20

          
21
  //Action methods
22

          
23
}



Once the repository instance is available, you can invoke its methods from the action methods in your controller classes to perform CRUD operations against the underlying database.

Use the Generic Repository

The other approach is to use a generic repository – we’ve already looked at it in the earlier section. The generated code contains a generic repository named EntityFrameworkRepository. You should first register an instance of this repository class as a scoped instance so that you can use this instance in all classes in this application.

The following code snippet illustrates how you can create an instance of the generic repository in the ConfigureServices method of the Startup class.

Java
 




xxxxxxxxxx
1
11


 
1
public void ConfigureServices(IServiceCollection services)
2

          
3
{
4

          
5
   services.AddScoped<IRepository<Product>>(x => 
6

          
7
      { return new EntityFrameworkRepository<Product>(new DemoModel()); });
8

          
9
   services.AddControllers();
10

          
11
}



You can now use this generic repository in your controller classes. The following code snippet shows how you can use the generic repository in the controller classes.

Java
 




xxxxxxxxxx
1
23


 
1
[Route("api/[controller]")]
2

          
3
[ApiController]
4

          
5
public class ProductController : ControllerBase
6

          
7
 {
8

          
9
    private readonly IRepository<Product> _repository;
10

          
11
    public DefaultController(EntityFrameworkRepository<Product> genericRepository)
12

          
13
        {
14

          
15
            _repository = genericRepository;
16

          
17
        }
18

          
19
 
20

          
21
     //Action methods
22

          
23
 }



Use the UnitOfWork Pattern

Unit Of Pattern can be used to create an abstraction layer between the data access layer and the business logic layer of an application - it helps us implement the repository pattern elegantly. The generated classes contain the IUnitOfWork interface and the EntityFrameworkUnitOfWork class. You can take advantage of these types to use UnitOfWork in your controller or business logic classes.

The following code snippet illustrates how you can take advantage of the unit of work to store a product record in the database.

Java
 




xxxxxxxxxx
1
13


 
1
using (EntityFrameworkUnitOfWork unitOfWork = new EntityFrameworkUnitOfWork(new DemoModel()))
2

          
3
 {
4

          
5
      unitOfWork.Context.Add(new Product {ID = 1, CategoryID = 3, Discontinued = false, ProductName = "ABC Laptop", 
6

          
7
      QuantityPerUnit = 5, ReorderLevel = 20, UnitPrice = 20000.00, UnitsInStock = 100});
8

          
9
 
10

          
11
      unitOfWork.Save();
12

          
13
 }



Summary

The Repository Pattern was first introduced as part of Domain-Driven Design in the year 2004. Since then it has become extremely popular and has been the design pattern of choice for abstracting calls from an application to the underlying database.

Proper use of the Repository pattern improves testability, code extensibility, and maintenance. In this article, we’ve examined how we can build a repository and encapsulate all calls to the database using the Entity Developer ORM tool.

Database Repository (version control) Relational database ASP.NET ASP.NET Core dev

Opinions expressed by DZone contributors are their own.

Related

  • MongoDB to Couchbase for Developers, Part 1: Architecture
  • Introduction to Couchbase for Oracle Developers and Experts: Part 4: Data Modeling
  • What Java Developers Need to Know About Geo-Distributed Databases
  • Introduction to Couchbase for Oracle Developers and Experts: Part 2 - Database Objects

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!