Creating A Class
Now that we have an understanding of how the application fits together, let's create our first class. Within our API project directory create a new folder named 'Entities'. Within this folder create a new class file named Product (Product.cs).
Note: I will cover why we call this directory 'Entities' later in this blog.
Add the following class definition.
namespace API.Entities
{
public class Product
{
public int Id { get; set; }
public required string Name { get; set; }
public required string Description { get; set; }
public long Price { get; set; }
}
}
Here is a quick breakdown of what is included and why.
Note: When a class has no explicitly defined constructor, C# provides a parameterless constructor by default.
The namespace
Namespaces in C# provide a way to organize, encapsulate, and group related types within a codebase, helping to improve code organization, prevent naming conflicts, and enhance readability. In accordance with C# convention, we have given this class the namespace 'API.Entities' aligning the directory structure with the namespace hierarchy.
The class declaration
Here we define the class with a public accessor with it's name Product.
Note: It is important we use public accessors in this class and we'll cover why next.
The properties and default constructor
In the example above we pass 4 fields with setters and getters to the default constructor: Id (which by default will become our primary key), Name, Description and Price. As Name and Description are reference types, so we specify they are required using the "required" key word. The reason we do not do this for the integers is they are value types, therefor they can not be null, if an integer or long is not set it's default value will be 0.
Entity Framework
In this project, we will be utilizing the Entity Framework, an object-relational mapping (ORM) framework for accessing and manipulating databases. The main purpose of Entity Framework is to simplify the process of accessing and manipulating data in databases by providing a higher-level abstraction layer. It eliminates the need for writing raw SQL queries and instead allows developers to work with the database using familiar object-oriented programming concepts.
When using Entity Framework, it is common practice to create a directory named "Entities" for storing entity classes. Entity classes typically map to the tables or collections in the underlying database, and as you have probably already guessed, the above class definition is our first entity.
Now that we have our first entity let's add the Entity Framework to our project.
A Brief Overview Of Adding Packages To A .Net Project
There are several ways to add packages to a .Net project.
NuGet: NuGet is a popular package manager for .NET projects. You can use the
NuGet Package Manager UI in Visual Studio or the NuGet command-line interface (CLI) to search for and install packages directly into your project.
.NET CLI: You can use the
dotnet add package command to add a package to your project. For example:
dotnet add package Microsoft.EntityFrameworkCore.Design --version 7.0.11
In the example above we use the
dotnet add command followed by the package name, followed by the version.
Package Manager Console: If you use the
Visual Studio IDE, there is a
Package Manager Console window where you can execute NuGet commands. You can use the Package Manager Console to install, update, and uninstall packages in your project.
Adding The Entity Framework
Before we progress to setting up the database we will add two packages.
dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 7.0.10
dotnet add package Microsoft.EntityFrameworkCore.Design --version 7.0.10
Note: Pick the package version best aligned with your version of .Net, in my case, I'm using version 7.0.10. If you cannot locate an exact match, pick the closest version.
So, let's briefly cover what we have added and why.
Microsoft.EntityFrameworkCore.Sqlite is a package that allows developers to use SQLite as a database provider in Entity Framework. (We will use this for development purposes only and later migrate over to PostgreSQL)
Microsoft.EntityFrameworkCore.Design is a package that includes design-time components for Entity Framework. It is used during development to enable functionalities such as migrations, scaffolding, and database operations. We will cover this more in-depth later on, however, if you are familiar with database migrations this is probably fairly self-explanatory.
Setting Up A Database Connection
With the necessary packages installed, we can now set up our database and establish a connection.
In your project directory create a new folder named 'Data'. Within this folder create a new C# class named StoreContext, and add the following.
using API.Entities;
using Microsoft.EntityFrameworkCore;
namespace API.Data
{
public class StoreContext : DbContext
{
public StoreContext(DbContextOptions options) : base(options)
{
}
public DbSet<Product> ?Products { get; set; }
}
}
Let's break down what we have added here.
using API.Entities: This line of code imports the namespace API.Entities enabling us to have access to Product within the StoreContext class.
using Microsoft.EntityFrameworkCore: This line of code imports the Microsoft.EntityFrameworkCore namespace, which provides the necessary classes and functionalities for working with Entity Framework.
public class StoreContext : DbContext: This line defines the StoreContext class, which is derived from the DbContext class provided by Entity Framework Core. The DbContext class is responsible for managing the connection and interaction with the underlying database.
public StoreContext(DbContextOptions options) : base(options): This is the constructor of the StoreContext class. It takes an instance of DbContextOptions as a parameter, which represents the options for configuring the DbContext. The : base(options) part calls the base class constructor of DbContext and passes the provided options.
public DbSet<Product> Products { get; set; }: This is a property of the StoreContext class. It represents a collection of Product entities that can be queried, inserted, updated, or deleted from the underlying database. The DbSet<Product> is a DbSet type provided by Entity Framework Core, which is used to interact with a specific entity type (Product in this case) in the database.
The StoreContext class is going to serve as the database context for the application. It provides a constructor to configure the context with options, such as the database connection string. Additionally, it defines a DbSet<Product> property named Products, which represents the collection of Product entities and allows CRUD operations on the underlying database table.
Before we proceed we have a few last steps configuration to do.
Add the following to Program.cs (Provided it isn't in the middleware block, it can be placed anywhere in the file. I personally placed it just below the existing services for readability, including the using statement at the very top.)
using Microsoft.EntityFrameworkCore;
builder.Services.AddDbContext<StoreContext>(opt => {
opt.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection"));
});
This code configures and adds a database context to the dependency injection container using the AddDbContext method. Let's take a look at this in its entirety.
builder.Services: builder refers to an instance of WebHostBuilder or HostBuilder. The Services property is used to configure and add services to the dependency injection container.
.AddDbContext<StoreContext>: This method adds StoreContext to the dependency injection container. As I previously alluded to, StoreContext will be responsible for interacting with the underlying database.
(opt => { opt.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection")); }): This is a lambda expression that configures the options for the StoreContext. The opt parameter is an instance of DbContextOptionsBuilder<StoreContext> that allows you to specify options for the database context.
opt.UseSqlite(...): This method configures the database provider to use SQLite as the underlying database.
builder.Configuration.GetConnectionString("DefaultConnection"): This retrieves the database connection string named "DefaultConnection" from the application's configuration. The connection string contains the necessary information to connect to the SQLite database.
Lastly, modify your appsettings.Development.json to look like the following.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Information"
}
},
"ConnectionStrings": {
"DefaultConnection": "Data source=store.db"
}
}
Here we specify our default database connection. As we are using SQLite at this stage our database will be a file named store.db.