Content

  • Relationship between Models
  • Navigation Property
  • Applying Migration in Layred Architecture
  • Adding Interfaces in Repository Project
  • Implementing Interfaces

Relationship between Models

  • One-to-One Relationship: In a one-to-one relationship, each instance of one class is associated with exactly one instance of another class, and vice versa (e.g.- User -> Address)
  • One-to-Many Relationship: In a one-to-many relationship, each instance of one class can be associated with multiple instances of another class, but each instance of the other class is associated with only one instance of the first class. (e.g.- Department->Employee)
  • Many-to-One Relationship: A many-to-one relationship is essentially the inverse of a one-to-many relationship. Each instance of one class can be associated with only one instance of another class, but each instance of the other class can be associated with multiple instances of the first class. (e.g.- Products->Category)
  • Many-to-Many Relationship: In a many-to-many relationship, instances of one class can be associated with multiple instances of another class, and vice versa. (e.g.-Stuents->Courses)

Navigation Property

  • A navigation property is a property on a class that allows navigation from one class instance to related instances in another class.
  • Navigation property is used to represent relationships between entities/classes.
  • IEnumerable: It is used to represent a sequence of items that can be iterated over.
  • ICollection: In Entity Framework Core, and more broadly in ORM frameworks, ICollection is often used as the type for navigation properties that represent a collection of related entities.
  • HashSet: HashSet is a collection type in .NET that represents a set of unique elements,Unlike lists or arrays, HashSet does not allow duplicate elements.

Example

Class File: Country Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test.Entities
{
    public class Country
    {
        public int Id { get; set; }

        public string Name { get; set; } = "Bharat";

        //Navigation Property
        public ICollection <State> states { get; set; }= new HashSet<State>();
    }
}

Class File: State Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test.Entities
{
    public class State
    {
        public int Id { get; set; }

        public string Name { get; set; } = "Maharashtra";

        public int CountryId { get; set; }

        //Navigation Property
        public Country? Country { get; set; }

        //Navigation Property
        public ICollection <District> districts { get; set; } = new HashSet<District>();
    }
}

Class File: District Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test.Entities
{
    public class District
    {
        public int Id { get; set; }

        public string Name { get; set; } = "Kolhapur";

        public int StateId { get; set; }

        //Navigation Property
        public State? State { get; set; }
    }
}

Applying Migration in Layred Architecture

Steps:

  1. Install/Add EF Core package reference in Repository project
  2. Create ApplicationDbContext class-Create Constructor and pass DbContextOptions
  3. Add DbSets in ApplicationDbContext
  4. Setup ConnectionString in appSettings.json
  5. pass connectionString to ApplicationDbContext from Program.cs
  6. Install/Add EF Core tools package reference to UI project
  7. Set UI project as startup project
  8. Open Package Manager Console -> Select Project (UI) -> apply migration
  9. Add MigrationsAssembly in program.cs as suggested in PM
  10. Apply migration again and update database

Adding Interfaces in Repository Project

In the Repository Pattern, interfaces play a significant role in defining contracts for data access operations. Interfaces provide a way to define the operations that a repository should support without specifying how those operations are implemented.

Steps:

  1. Create new folder-"Interfaces"- in Repository project
  2. Create new Intefaces in folder (name must start with I)
  3. Write required method signatures in Intefaces

Example: Inteface File

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Test.Entities;

namespace Test.Repositories.Interfaces
{
    public interface ICountryRepo
    {
        IEnumerable<Country> GetAll();

        Country GetById(int id);

        void Save(Country country);

        void Edit(Country country);

        void RemoveData(Country country);


    }
}

Implementing Interfaces

Steps:

  1. Create new folder-"Implementations"- in Repository project
  2. Create class file
  3. Inherit this new class with respective Inteface
  4. Implement Inteface
  5. Create ApplicationDbContext field in class
  6. Inject ApplicationDbContext in class using constructor
  7. Write method definations using EF Core

Example: Class File

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Test.Entities;
using Test.Repositories.Interfaces;

namespace Test.Repositories.Implementations
{
    public class CountryRepo : ICountryRepo
    {
        private readonly ApplicationDbContext _context;

        public CountryRepo(ApplicationDbContext context)
        {
            _context = context;
        }

        public void Edit(Country country)
        {
            _context.Countries.Update(country);
            _context.SaveChanges();
        }

        public IEnumerable<Country> GetAll()
        {
            var countries = _context.Countries.ToList();
            return countries;
        }

        public Country GetById(int id)
        {
            var country = _context.Countries.Find(id);
            return country;
        }

        public void RemoveData(Country country)
        {
            _context.Remove(country);
            _context.SaveChanges();
        }

        public void Save(Country country)
        {
           _context.Add(country);
            _context.SaveChanges();
        }
    }
}