Onion architecture in the development of cross platform applications. Part 3. Infrastructure

Onion architecture in the development of cross platform applications. Part 3. Infrastructure

21 September 2021

.NET

Buy Me A Coffee

Hello!

This is a continuation of the second article about onion architecture in the development of cross-platform applications.

We continue creating PizzaStore.

In this article, we are moving to the outer layer, which will implement the data interfaces.

Because we develop a cross-platform application we'll create Infrastructure projects for each application - Web and Mobile.

Let's start with the WebApp.

To do this, let's add the Class Library project and name it PizzaStore.Infrastructure.WebApp.Data.

This project will implement the Application layer interfaces. MS SQL Server will be used as storage, with which we will interact through the Entity Framework Core.

The benefit of the separation is you can easily replace the Database, ORM Framework, e.g. MySQL and Dapper.

Therefore, we will add all the NuGet Microsoft.EntityFrameworkCore packages to this project. We will also add the PizzaStore.Application project reference to the project.

After that, add a new WebAppContext class to the project:

namespace PizzaStore.Infrastructure.WebApp.Data.Repositories.Models;

using Microsoft.EntityFrameworkCore;

public class WebAppContext : DbContext
{
	public WebAppContext(DbContextOptions<WebAppContext> options)
		: base(options)
	{
	}

	public virtual DbSet<Pizza> Pizza => Set<Pizza>();

	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		modelBuilder.Entity<Pizza>(entity =>
		{
			entity.HasIndex(e => e.Name).IsUnique();
		});
	}
}

We also need to implement our IPizzaRepository:

public class PizzaRepository : IPizzaRepository
{
	private readonly WebAppContext db;

	public PizzaRepository(WebAppContext db)
	{
		this.db = db;
	}

	public Task<List<Pizza>> GetAll()
	{
		return db.Pizza.ToListAsync();
	}

	public Task<Pizza?> GetById(int id)
	{
		return db.Pizza.SingleOrDefaultAsync(x => x.Id == id);
	}

	public async Task<Pizza> Create(Pizza pizza)
	{
		await db.Pizza.AddAsync(pizza);
		await db.SaveChangesAsync();
		return pizza;
	}

	public async Task Update(Pizza pizza)
	{
		db.Entry(pizza).State = EntityState.Modified;
		await db.SaveChangesAsync();
	}

	public async Task Delete(int id)
	{
		var pizza = await db.Pizza.SingleOrDefaultAsync(x => x.Id == id);
		if (pizza != null)
		{
			db.Pizza.Remove(pizza);
			await db.SaveChangesAsync();
		}
	}
}

The final step is registration the db connection:

services.AddDbContext<StaffingContext>(opts => opts.UseSqlServer(configuration.GetConnectionString("MSSQLConnection")));
services.AddTransient<IPizzaRepository, PizzaRepository>();

For the Mobile application, the steps are the same. The difference is only in DB initialization:

services.AddDbContext<StaffingContext>(opts => opts.UseSqlite(configuration.GetConnectionString("SqliteConnection")));
services.AddTransient<IPizzaRepository, PizzaRepository>();

In the next article, we'll create UI level: Onion architecture in the development of cross-platform applications. Part 4. UI

Buy Me A Coffee

Related:

Onion architecture in the development of cross platform applications. Part 1. Overview

Overview of onion architecture. Creating a cross-platform application with the onion architecture.

Onion architecture in the development of cross platform applications. Part 4. UI

Overview of onion architecture. Creating a cross-platform application with the onion architecture.

An unhandled error has occurred. Reload

🗙