Configure Many-to-Many Relationships using Fluent API in Entity Framework Core

public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }
}

public class Course
{
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public string Description { get; set; }
}
public class StudentCourse
{
    public int StudentId { get; set; }
    public Student Student { get; set; }

    public int CourseId { get; set; }
    public Course Course { get; set; }
}

public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }

    public IList<StudentCourse> StudentCourses { get; set; }
}

public class Course
{
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public string Description { get; set; }

    public IList<StudentCourse> StudentCourses { get; set; }
}
public class SchoolContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=.\\SQLEXPRESS;Database=EFCore-SchoolDB;Trusted_Connection=True");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<StudentCourse>().HasKey(sc => new { sc.StudentId, sc.CourseId });
    }
    
    public DbSet<Student> Students { get; set; }
    public DbSet<Course> Courses { get; set; }
    public DbSet<StudentCourse> StudentCourses { get; set; }
}

References
https://www.entityframeworktutorial.net/efcore/configure-many-to-many-relationship-in-ef-core.aspx

Configure One-to-One Relationships using Fluent API in Entity Framework Core

using Microsoft.EntityFrameworkCore;

namespace BlazorApp1;

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

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseNpgsql("Host=localhost;Database=testdb;Username=postgres;Password=12345");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Student>()
            .HasOne<StudentAddress>(s => s.Address)
            .WithOne(ad => ad.Student)
            .HasForeignKey<StudentAddress>(ad => ad.AddressOfStudentId);
    }

    public DbSet<Student> Students { get; set; }
    public DbSet<StudentAddress> StudentAddresses { get; set; }
}

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }

    public StudentAddress Address { get; set; }
}

public class StudentAddress
{
    public int StudentAddressId { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public int AddressOfStudentId { get; set; }
    public Student Student { get; set; }
}

References
https://www.entityframeworktutorial.net/efcore/configure-one-to-one-relationship-using-fluent-api-in-ef-core.aspx
https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key

Configure One-to-Many Relationships using Fluent API in Entity Framework Core

 

using Microsoft.EntityFrameworkCore;

namespace BlazorApp1;

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

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseNpgsql("Host=localhost;Database=testdb;Username=postgres;Password=12345");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Student>()
            .HasOne<Grade>(s => s.Grade)
            .WithMany(g => g.Students)
            .HasForeignKey(s => s.CurrentGradeId);
    }

    public DbSet<Student> Students { get; set; }
    public DbSet<Grade> Grades { get; set; }
}

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int CurrentGradeId { get; set; }
    public Grade Grade { get; set; }
}

public class Grade
{
    public int GradeId { get; set; }
    public string GradeName { get; set; }
    public string Section { get; set; }

    public ICollection<Student> Students { get; set; }
}

References
https://www.entityframeworktutorial.net/efcore/configure-one-to-many-relationship-using-fluent-api-in-ef-core.aspx
https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key

Entity Framework Core tools reference – .NET Core CLI

Installing the tools

dotnet ef can be installed as either a global or local tool.

dotnet tool install --global dotnet-ef
dotnet new tool-manifest # if you are setting up this repo
dotnet tool install --local dotnet-ef

Before you can use the tools on a specific project, you’ll need to add the Microsoft.EntityFrameworkCore.Design package to it.

dotnet add package Microsoft.EntityFrameworkCore.Design

Update the tools

Use dotnet tool update --global dotnet-ef to update the global tools to the latest available version. If you have the tools installed locally in your project use dotnet tool update dotnet-ef. Install a specific version by appending --version <VERSION> to your command. See the Update section of the dotnet tool documentation for more details.

Usefull Commands

dotnet ef database drop

Deletes the database.

dotnet ef database update

Updates the database to the last migration or to a specified migration.

dotnet ef dbcontext info

Gets information about a DbContext type.

dotnet ef dbcontext list

Lists available DbContext types.

dotnet ef dbcontext optimize

Generates a compiled version of the model used by the DbContext. Added in EF Core 6.

dotnet ef dbcontext scaffold

Generates code for a DbContext and entity types for a database. In order for this command to generate an entity type, the database table must have a primary key.

dotnet ef dbcontext script

Generates a SQL script from the DbContext. Bypasses any migrations.

dotnet ef migrations add

Adds a new migration.

dotnet ef migrations bundle

Creates an executable to update the database.

dotnet ef migrations list

Lists available migrations.

dotnet ef migrations remove

Removes the last migration, rolling back the code changes that were done for the latest migration.

dotnet ef migrations script

Generates a SQL script from migrations.

Reverting a Migration

Suppose you changed your domain class and created the second migration named MySecondMigration using the add-migration command and applied this migration to the database using the Update command. But, for some reason, you want to revert the database to the previous state. In this case, use the update-database <migration name> command to revert the database to the specified previous migration snapshot.

dotnet ef database update MyFirstMigration

The above command will revert the database based on a migration named MyFirstMigration and remove all the changes applied for the second migration named MySecondMigration. This will also remove MySecondMigration entry from the __EFMigrationsHistory table in the database.

Note: This will not remove the migration files related to MySecondMigration. Use the remove commands to remove them from the project.

References
https://docs.microsoft.com/en-us/ef/core/cli/dotnet

Configure PostgreSQL Entity Framework for ASP.NET using Npgsql

Install Required Packages

dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore

Install dotnet-ef

Install it locally or globally.

Local

dotnet new tool-manifest # if you are setting up this repo
dotnet tool install --local dotnet-ef

Global

dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design

Defining a DbContext

using Microsoft.EntityFrameworkCore;

namespace BlazorApp1;

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

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseNpgsql("Host=localhost;Database=testdb;Username=postgres;Password=12345");
    }

    public DbSet<Person> People { get; set; }
}

public class Person
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

Create Migration

dotnet ef migrations add InitialCreate

Apply to Database

dotnet ef database update

or

dotnet ef database update InitialCreate
dotnet ef database update 20180904195021_InitialCreate --connection your_connection_string

Program.cs

builder.Services.AddDbContext<AppDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("AppDbContext")));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

References
https://www.npgsql.org/efcore/index.html
https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/intro?view=aspnetcore-6.0&tabs=visual-studio
https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/migrations?view=aspnetcore-6.0
https://medium.com/executeautomation/asp-net-core-6-0-minimal-api-with-entity-framework-core-69d0c13ba9ab
https://docs.microsoft.com/en-us/ef/core/cli/dotnet

Install PostgreSQL on Ubuntu 22.04

# Create the file repository configuration:
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

# Import the repository signing key:
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

# Update the package lists:
sudo apt-get update

# Install the latest version of PostgreSQL.
# If you want a specific version, use 'postgresql-12' or similar instead of 'postgresql':
sudo apt-get -y install postgresql postgresql-contrib
sudo systemctl start postgresql.service

Update PostgreSQL admin user’s password

The postgresql database admin user is created with the installation of PostgreSQL database server. We need to set a secure password for this user.

sudo su - postgres
psql -c "alter user postgres with password 'MySt0ngDBP@ss'"

Switching Over to the postgres Account

Switch over to the postgres account on your server by typing:

sudo -i -u postgres

You can now access the PostgreSQL prompt immediately by typing:

psql

From there you are free to interact with the database management system as necessary.
Exit out of the PostgreSQL prompt by typing:

\q

This will bring you back to the postgres Linux user’s command prompt.

Accessing a Postgres Prompt Without Switching Accounts

sudo -u postgres psql
\q

References
https://www.digitalocean.com/community/tutorials/how-to-install-postgresql-on-ubuntu-22-04-quickstart
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-22-04
https://computingforgeeks.com/installing-postgresql-database-server-on-ubuntu/

Handling Form submission with Validation in Blazor

The EditForm component is Blazor’s approach to managing user-input in a way that makes it easy to perform validation against user input. It also provides the ability to check if all validation rules have been satisfied, and present the user with validation errors if they have not.

The EditForm provides the following callbacks for handling form submission:

  • Use OnValidSubmit to assign an event handler to run when a form with valid fields is submitted.
  • Use OnInvalidSubmit to assign an event handler to run when a form with invalid fields is submitted.
  • Use OnSubmit to assign an event handler to run regardless of the form fields’ validation status. The form is validated by calling EditContext.Validate in the event handler method. If Validate returns true, the form is valid.
@page "/"
@using System.ComponentModel.DataAnnotations

<EditForm Model="@person" OnSubmit="FormSubmit">
    <DataAnnotationsValidator/>
    <ValidationSummary/>
    <div class="mb-3">
        <label for="inputFirstName" class="form-label">First Name</label>
        <InputText @bind-Value="person.FirstName" class="form-control" id="inputFirstName"></InputText>
    </div>
    <div class="mb-3">
        <label for="inputLastName" class="form-label">Last Name</label>
        <InputText @bind-Value="person.LastName" class="form-control" id="inputLastName"></InputText>
    </div>
    <div class="mb-3">
        <label for="inputAge" class="form-label">Age</label>
        <InputNumber @bind-Value="person.Age" class="form-control" id="inputAge"></InputNumber>
    </div>

    <input type="submit" class="btn btn-primary" value="Save"/>
</EditForm>

<div>Form validation : @isFormValid</div>

@code
{

    private Person person = new();
    private bool isFormValid = false;

    public class Person
    {
        public int Id { get; set; }

        [Required(ErrorMessage = "First Name is empty")]
        public string? FirstName { get; set; }

        [Required(ErrorMessage = "Last Name is empty")]
        public string? LastName { get; set; }

        [Required]
        [Range(0, 150, ErrorMessage = "Age is not in range")]
        public int Age { get; set; } = 36;
    }

    private void FormSubmit(EditContext editContext)
    {
        if (editContext.Validate())
        {
            isFormValid = true;
        }
    }
}

You can use ValidationMessage Component instead of ValidationSummary Component to show error message for each field.

<EditForm Model="@person" OnSubmit="FormSubmit">
    <DataAnnotationsValidator/>
    <div class="mb-3">
        <label for="inputFirstName" class="form-label">First Name</label>
        <InputText @bind-Value="person.FirstName" class="form-control" id="inputFirstName"></InputText>
        <ValidationMessage For="() => person.FirstName"></ValidationMessage>
    </div>
    <div class="mb-3">
        <label for="inputLastName" class="form-label">Last Name</label>
        <InputText @bind-Value="person.LastName" class="form-control" id="inputLastName"></InputText>
        <ValidationMessage For="() => person.LastName"></ValidationMessage>
    </div>
    <div class="mb-3">
        <label for="inputAge" class="form-label">Age</label>
        <InputNumber @bind-Value="person.Age" class="form-control" id="inputAge"></InputNumber>
        <ValidationMessage For="() => person.Age"></ValidationMessage>
    </div>

    <input type="submit" class="btn btn-primary" value="Save"/>
</EditForm>

 

References
https://blazor-university.com/forms/handling-form-submission/
https://docs.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-6.0

Install and Configure ProxyChains on Ubuntu

Install

Download source code from here

# needs a working C compiler, preferably gcc
./configure
make
sudo make install

Configure

sudo nano /etc/proxychains.conf
# proxychains.conf  VER 4
#
#        HTTP, SOCKS4, SOCKS5 tunneling proxifier with DNS.
#	

# The option below identifies how the ProxyList is treated.
# only one option should be uncommented at time,
# otherwise the last appearing option will be accepted
#
#dynamic_chain
#
# Dynamic - Each connection will be done via chained proxies
# all proxies chained in the order as they appear in the list
# at least one proxy must be online to play in chain
# (dead proxies are skipped)
# otherwise EINTR is returned to the app
#
strict_chain
#
# Strict - Each connection will be done via chained proxies
# all proxies chained in the order as they appear in the list
# all proxies must be online to play in chain
# otherwise EINTR is returned to the app
#
#random_chain
#
# Random - Each connection will be done via random proxy
# (or proxy chain, see  chain_len) from the list.
# this option is good to test your IDS :)

# Make sense only if random_chain
#chain_len = 2

# Quiet mode (no output from library)
#quiet_mode

# Proxy DNS requests - no leak for DNS data
proxy_dns 

# set the class A subnet number to usefor use of the internal remote DNS mapping
# we use the reserved 224.x.x.x range by default,
# if the proxified app does a DNS request, we will return an IP from that range.
# on further accesses to this ip we will send the saved DNS name to the proxy.
# in case some control-freak app checks the returned ip, and denies to 
# connect, you can use another subnet, e.g. 10.x.x.x or 127.x.x.x.
# of course you should make sure that the proxified app does not need
# *real* access to this subnet. 
# i.e. dont use the same subnet then in the localnet section
#remote_dns_subnet 127 
#remote_dns_subnet 10
remote_dns_subnet 224

# Some timeouts in milliseconds
tcp_read_time_out 15000
tcp_connect_time_out 8000

# By default enable localnet for loopback address ranges
# RFC5735 Loopback address range
localnet 127.0.0.0/255.0.0.0
# RFC1918 Private Address Ranges
# localnet 10.0.0.0/255.0.0.0
# localnet 172.16.0.0/255.240.0.0
# localnet 192.168.0.0/255.255.0.0


# Example for localnet exclusion
## Exclude connections to 192.168.1.0/24 with port 80
# localnet 192.168.1.0:80/255.255.255.0

## Exclude connections to 192.168.100.0/24
# localnet 192.168.100.0/255.255.255.0

## Exclude connections to ANYwhere with port 80
# localnet 0.0.0.0:80/0.0.0.0


### Examples for dnat
## Trying to proxy connections to destinations which are dnatted,
## will result in proxying connections to the new given destinations.
## Whenever I connect to 1.1.1.1 on port 1234 actually connect to 1.1.1.2 on port 443
# dnat 1.1.1.1:1234  1.1.1.2:443

## Whenever I connect to 1.1.1.1 on port 443 actually connect to 1.1.1.2 on port 443
## (no need to write :443 again)
# dnat 1.1.1.2:443  1.1.1.2

## No matter what port I connect to on 1.1.1.1 port actually connect to 1.1.1.2 on port 443
# dnat 1.1.1.1  1.1.1.2:443

## Always, instead of connecting to 1.1.1.1, connect to 1.1.1.2
# dnat 1.1.1.1  1.1.1.2


# ProxyList format
#       type  host  port [user pass]
#       (values separated by 'tab' or 'blank')
#
#
#        Examples:
#
#            	socks5	192.168.67.78	1080	lamer	secret
#		http	192.168.89.3	8080	justu	hidden
#	 	socks4	192.168.1.49	1080
#	        http	192.168.39.93	8080	
#		
#
#       proxy types: http, socks4, socks5, raw
#        * raw: The traffic is simply forwarded to the proxy without modification.
#        ( auth types supported: "basic"-http  "user/pass"-socks )
#
[ProxyList]

socks5 127.0.0.1 1080

Check

wget -qO - icanhazip.com
proxychains4 wget -qO - icanhazip.com

References
https://github.com/haad/proxychains
https://github.com/haad/proxychains/blob/master/src/proxychains.conf
https://www.linuxbabe.com/desktop-linux/how-to-use-proxychains-to-redirect-your-traffic-through-proxy-server

Navigating in Blazor using the NavLink component

Use a NavLink component in place of HTML hyperlink elements (<a>) when creating navigation links. A NavLink component behaves like an <a> element, except it toggles an active CSS class based on whether its href matches the current URL. The active class helps a user understand which page is the active page among the navigation links displayed. Optionally, assign a CSS class name to NavLink.ActiveClass to apply a custom CSS class to the rendered link when the current route matches the href.

<nav class="flex-column">
    <div class="nav-item px-3">
        <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
            <span class="oi oi-home" aria-hidden="true"></span> Home
        </NavLink>
    </div>
    <div class="nav-item px-3">
        <NavLink class="nav-link" href="counter">
            <span class="oi oi-plus" aria-hidden="true"></span> Counter
        </NavLink>
    </div>
    <div class="nav-item px-3">
        <NavLink class="nav-link" href="fetchdata">
            <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
        </NavLink>
    </div>
</nav>

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-6.0#navlink-and-navmenu-components
https://blazor-university.com/routing/navigating-our-app-via-html/