πŸ“± ASP.NET Core MVC Mobile Shop – Part 3: Configure Database & Entity Framework Core

 

πŸ“± ASP.NET Core MVC Mobile Shop – Part 3: Models, DbContext, Database Setup & Seeding

πŸš€ Introduction

Welcome to Part 3 of our Mobile Shop Website using ASP.NET Core MVC series.

In this part, we will build the core foundation of our application, including:

  • Creating all required Models
  • Configuring ApplicationDbContext
  • Setting up ASP.NET Identity
  • Implementing Database Seeding (DbInitializer)
  • Running Migrations & Database Update

This step transforms our project into a fully structured eCommerce backend system.


🎯 What You Will Learn

In this tutorial, you will learn:

  • How to design real-world eCommerce models
  • How to configure DbContext with relationships
  • How to integrate Identity with custom user
  • How to seed roles and admin user
  • How to create and update database

🧱 Step 1: Create Models

Create a Models folder and add the following classes:


πŸ”Ή ApplicationUser (Extend Identity)

C# / ApplicationUser.cs
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;

namespace MobileShop.Models
{
    public class ApplicationUser : IdentityUser
    {
        [Required]
        [Display(Name = "First Name")]
        [StringLength(50)]
        public string FirstName { get; set; } = string.Empty;

        [Required]
        [Display(Name = "Last Name")]
        [StringLength(50)]
        public string LastName { get; set; } = string.Empty;

        [Display(Name = "Full Name")]
        public string FullName => $"{FirstName} {LastName}";

        [StringLength(200)]
        public string? Address { get; set; }

        [StringLength(100)]
        public string? City { get; set; }

        [StringLength(20)]
        public string? PostalCode { get; set; }

        [StringLength(50)]
        public string? Country { get; set; } = "Pakistan";

        [StringLength(255)]
        public string? ProfileImageUrl { get; set; }

        [DataType(DataType.Date)]
        [Display(Name = "Date of Birth")]
        public DateTime? DateOfBirth { get; set; }

        [Display(Name = "Member Since")]
        [DataType(DataType.DateTime)]
        public DateTime CreatedAt { get; set; } = DateTime.Now;

        public bool IsActive { get; set; } = true;

        // Navigation Properties
        public virtual ICollection<Order> Orders { get; set; } = new List<Order>();
        public virtual ICollection<Review> Reviews { get; set; } = new List<Review>();
        public virtual ICollection<WishlistItem> WishlistItems { get; set; } = new List<WishlistItem>();
    }
}

πŸ”Ή Brand


C# / Brand.cs
using System.ComponentModel.DataAnnotations;

namespace MobileShop.Models
{
    public class Brand
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(100)]
        [Display(Name = "Brand Name")]
        public string Name { get; set; } = string.Empty;

        [StringLength(500)]
        public string? Description { get; set; }

        [StringLength(255)]
        [Display(Name = "Logo URL")]
        public string? LogoUrl { get; set; }

        [StringLength(100)]
        public string? Country { get; set; }

        [StringLength(255)]
        [Display(Name = "Official Website")]
        public string? WebsiteUrl { get; set; }

        public bool IsActive { get; set; } = true;

        [DataType(DataType.DateTime)]
        public DateTime CreatedAt { get; set; } = DateTime.Now;

        // Navigation Properties
        public virtual ICollection<Product> Products { get; set; } = new List<Product>();
    }
}

πŸ”Ή Category


C# / Category.cs
using System.ComponentModel.DataAnnotations;

namespace MobileShop.Models
{
    public class Category
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(100)]
        [Display(Name = "Category Name")]
        public string Name { get; set; } = string.Empty;

        [StringLength(500)]
        public string? Description { get; set; }

        [StringLength(255)]
        [Display(Name = "Image URL")]
        public string? ImageUrl { get; set; }

        [Display(Name = "Display Order")]
        public int DisplayOrder { get; set; }

        public bool IsActive { get; set; } = true;

        [DataType(DataType.DateTime)]
        public DateTime CreatedAt { get; set; } = DateTime.Now;

        // Navigation Properties
        public virtual ICollection<Product> Products { get; set; } = new List<Product>();
    }
}

πŸ”Ή Product


C# / Product.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MobileShop.Models
{
    public class Product
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(200)]
        [Display(Name = "Product Name")]
        public string Name { get; set; } = string.Empty;

        [StringLength(100)]
        public string? Model { get; set; }

        [StringLength(2000)]
        public string? Description { get; set; }

        [StringLength(1000)]
        [Display(Name = "Short Description")]
        public string? ShortDescription { get; set; }

        [Required]
        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Original Price")]
        public decimal OriginalPrice { get; set; }

        [Required]
        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Sale Price")]
        public decimal SalePrice { get; set; }

        [Display(Name = "Discount Percentage")]
        public int DiscountPercentage => OriginalPrice > 0 
            ? (int)((OriginalPrice - SalePrice) / OriginalPrice * 100) 
            : 0;

        [Display(Name = "Stock Quantity")]
        public int StockQuantity { get; set; } = 0;

        [StringLength(255)]
        [Display(Name = "Main Image")]
        public string? MainImageUrl { get; set; }

        public bool IsFeatured { get; set; } = false;
        public bool IsNewArrival { get; set; } = false;
        public bool IsBestseller { get; set; } = false;
        public bool IsActive { get; set; } = true;

        // Foreign Keys
        [Display(Name = "Category")]
        public int CategoryId { get; set; }

        [Display(Name = "Brand")]
        public int BrandId { get; set; }

        // Navigation Properties
        [ForeignKey("CategoryId")]
        public virtual Category Category { get; set; } = null!;

        [ForeignKey("BrandId")]
        public virtual Brand Brand { get; set; } = null!;

        public virtual ICollection<ProductImage> ProductImages { get; set; } = new List<ProductImage>();
        public virtual ICollection<ProductSpecification> Specifications { get; set; } = new List<ProductSpecification>();
        public virtual ICollection<Review> Reviews { get; set; } = new List<Review>();
        public virtual ICollection<OrderItem> OrderItems { get; set; } = new List<OrderItem>();
        public virtual ICollection<WishlistItem> WishlistItems { get; set; } = new List<WishlistItem>();

        [DataType(DataType.DateTime)]
        public DateTime CreatedAt { get; set; } = DateTime.Now;

        [DataType(DataType.DateTime)]
        public DateTime? UpdatedAt { get; set; }

        // Computed Properties
        [Display(Name = "Average Rating")]
        public double AverageRating => Reviews.Any() ? Reviews.Average(r => r.Rating) : 0;

        [Display(Name = "Review Count")]
        public int ReviewCount => Reviews.Count;
    }
}


πŸ”Ή ProductImage


C# / ProductImage.cs
 using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MobileShop.Models
{
    public class ProductImage
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(500)]
        [Display(Name = "Image URL")]
        public string ImageUrl { get; set; } = string.Empty;

        [StringLength(200)]
        public string? AltText { get; set; }

        [Display(Name = "Display Order")]
        public int DisplayOrder { get; set; }

        [Display(Name = "Is Main Image")]
        public bool IsMainImage { get; set; } = false;

        // Foreign Key
        [Display(Name = "Product")]
        public int ProductId { get; set; }

        [ForeignKey("ProductId")]
        public virtual Product Product { get; set; } = null!;
    }
}

πŸ”Ή ProductSpecification


C# / ProductSpecification.cs
  using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MobileShop.Models
{
    public class ProductSpecification
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(100)]
        [Display(Name = "Specification Name")]
        public string Name { get; set; } = string.Empty;

        [Required]
        [StringLength(500)]
        [Display(Name = "Specification Value")]
        public string Value { get; set; } = string.Empty;

        [StringLength(50)]
        [Display(Name = "Group Name")]
        public string? GroupName { get; set; }

        [Display(Name = "Display Order")]
        public int DisplayOrder { get; set; }

        // Foreign Key
        [Display(Name = "Product")]
        public int ProductId { get; set; }

        [ForeignKey("ProductId")]
        public virtual Product Product { get; set; } = null!;
    }
}

πŸ”Ή Review


C# / Review.cs
  using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MobileShop.Models
{
    public class Review
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [Range(1, 5)]
        public int Rating { get; set; }

        [StringLength(1000)]
        public string? Comment { get; set; }

        [StringLength(100)]
        public string? Title { get; set; }

        public bool IsVerifiedPurchase { get; set; } = false;
        public bool IsApproved { get; set; } = false;

        // Foreign Keys
        [Display(Name = "Product")]
        public int ProductId { get; set; }

        [Display(Name = "User")]
        public string UserId { get; set; } = string.Empty;

        // Navigation Properties
        [ForeignKey("ProductId")]
        public virtual Product Product { get; set; } = null!;

        [ForeignKey("UserId")]
        public virtual ApplicationUser User { get; set; } = null!;

        [DataType(DataType.DateTime)]
        public DateTime CreatedAt { get; set; } = DateTime.Now;
    }
}

πŸ”Ή ShoppingCartItem


C# / ShoppingCartItem.cs
  using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MobileShop.Models
{
    public class ShoppingCartItem
    {
        [Key]
        public int Id { get; set; }

        [Required]
        public string CartId { get; set; } = string.Empty;

        [Required]
        public int Quantity { get; set; } = 1;

        [DataType(DataType.DateTime)]
        public DateTime CreatedAt { get; set; } = DateTime.Now;

        // Foreign Key
        [Display(Name = "Product")]
        public int ProductId { get; set; }

        // Navigation Properties
        [ForeignKey("ProductId")]
        public virtual Product Product { get; set; } = null!;

        // Computed Properties
        [Column(TypeName = "decimal(18,2)")]
        public decimal TotalPrice => Product != null ? Product.SalePrice * Quantity : 0;
    }
}

πŸ”Ή WishlistItem


C# / WishlistItem.cs
  using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MobileShop.Models
{
    public class WishlistItem
    {
        [Key]
        public int Id { get; set; }

        [DataType(DataType.DateTime)]
        public DateTime AddedAt { get; set; } = DateTime.Now;

        // Foreign Keys
        [Display(Name = "Product")]
        public int ProductId { get; set; }

        [Display(Name = "User")]
        public string UserId { get; set; } = string.Empty;

        // Navigation Properties
        [ForeignKey("ProductId")]
        public virtual Product Product { get; set; } = null!;

        [ForeignKey("UserId")]
        public virtual ApplicationUser User { get; set; } = null!;
    }
}

πŸ”Ή Order


C# / Order.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MobileShop.Models
{
    public enum OrderStatus
    {
        Pending,
        Processing,
        Shipped,
        Delivered,
        Cancelled,
        Refunded
    }

    public enum PaymentStatus
    {
        Pending,
        Paid,
        Failed,
        Refunded
    }

    public enum PaymentMethod
    {
        CreditCard,
        DebitCard,
        PayPal,
        Stripe,
        CashOnDelivery,
        UPI
    }

    public class Order
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(35)]
        [Display(Name = "Order Number")]
        public string OrderNumber { get; set; } = GenerateOrderNumber();

        [Required]
        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Subtotal")]
        public decimal Subtotal { get; set; }

        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Tax Amount")]
        public decimal TaxAmount { get; set; }

        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Shipping Cost")]
        public decimal ShippingCost { get; set; }

        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Discount Amount")]
        public decimal DiscountAmount { get; set; }

        [Required]
        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Total Amount")]
        public decimal TotalAmount { get; set; }

        [Display(Name = "Order Status")]
        public OrderStatus Status { get; set; } = OrderStatus.Pending;

        [Display(Name = "Payment Status")]
        public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Pending;

        [Display(Name = "Payment Method")]
        public PaymentMethod PaymentMethod { get; set; }

        [StringLength(100)]
        [Display(Name = "Transaction ID")]
        public string? TransactionId { get; set; }

        // Shipping Address
        [Required]
        [StringLength(200)]
        [Display(Name = "Shipping Address")]
        public string ShippingAddress { get; set; } = string.Empty;

        [Required]
        [StringLength(100)]
        [Display(Name = "City")]
        public string ShippingCity { get; set; } = string.Empty;

        [StringLength(20)]
        [Display(Name = "Postal Code")]
        public string? ShippingPostalCode { get; set; }

        [StringLength(50)]
        [Display(Name = "Country")]
        public string ShippingCountry { get; set; } = "Pakistan";

        [StringLength(20)]
        [Display(Name = "Phone Number")]
        public string? ShippingPhone { get; set; }

        [StringLength(500)]
        [Display(Name = "Order Notes")]
        public string? Notes { get; set; }

        [DataType(DataType.DateTime)]
        [Display(Name = "Order Date")]
        public DateTime OrderDate { get; set; } = DateTime.Now;

        [DataType(DataType.DateTime)]
        [Display(Name = "Shipped Date")]
        public DateTime? ShippedDate { get; set; }

        [DataType(DataType.DateTime)]
        [Display(Name = "Delivered Date")]
        public DateTime? DeliveredDate { get; set; }

        // Foreign Key
        [Display(Name = "Customer")]
        public string? UserId { get; set; }

        [ForeignKey("UserId")]
        public virtual ApplicationUser? User { get; set; }

        // Navigation Properties
        public virtual ICollection<OrderItem> OrderItems { get; set; } = new List<OrderItem>();

        private static string GenerateOrderNumber()
        {
            return $"ORD-{DateTime.Now:yyyyMMdd}-{Guid.NewGuid().ToString().Substring(0, 8).ToUpper()}";
        }
    }
}


πŸ”Ή OrderItem


C# / OrderItem.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MobileShop.Models
{
    public class OrderItem
    {
        [Key]
        public int Id { get; set; }

        [Required]
        public int Quantity { get; set; }

        [Required]
        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Unit Price")]
        public decimal UnitPrice { get; set; }

        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Discount")]
        public decimal Discount { get; set; }

        [Required]
        [Column(TypeName = "decimal(18,2)")]
        [Display(Name = "Total Price")]
        public decimal TotalPrice => (UnitPrice * Quantity) - Discount;

        // Foreign Keys
        [Display(Name = "Order")]
        public int OrderId { get; set; }

        [Display(Name = "Product")]
        public int ProductId { get; set; }

        // Navigation Properties
        [ForeignKey("OrderId")]
        public virtual Order Order { get; set; } = null!;

        [ForeignKey("ProductId")]
        public virtual Product Product { get; set; } = null!;
    }
}


πŸ—„️ Step 2: Create ApplicationDbContext

Create inside Data folder:


C# / ApplicationDbContext.cs

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using MobileShop.Models;

namespace MobileShop.Data
{
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        public DbSet<Category> Categories { get; set; }
        public DbSet<Brand> Brands { get; set; }
        public DbSet<Product> Products { get; set; }
        public DbSet<ProductImage> ProductImages { get; set; }
        public DbSet<ProductSpecification> ProductSpecifications { get; set; }
        public DbSet<Review> Reviews { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderItem> OrderItems { get; set; }
        public DbSet<ShoppingCartItem> ShoppingCartItems { get; set; }
        public DbSet<WishlistItem> WishlistItems { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // Configure relationships and constraints
            modelBuilder.Entity<Product>(entity =>
            {
                entity.HasOne(p => p.Category)
                      .WithMany(c => c.Products)
                      .HasForeignKey(p => p.CategoryId)
                      .OnDelete(DeleteBehavior.Restrict);

                entity.HasOne(p => p.Brand)
                      .WithMany(b => b.Products)
                      .HasForeignKey(p => p.BrandId)
                      .OnDelete(DeleteBehavior.Restrict);

                entity.HasIndex(p => p.Name);
                entity.HasIndex(p => p.IsFeatured);
                entity.HasIndex(p => p.IsNewArrival);
                entity.HasIndex(p => p.IsBestseller);
            });

            modelBuilder.Entity<Order>(entity =>
            {
                entity.HasIndex(o => o.OrderNumber).IsUnique();
                entity.HasIndex(o => o.Status);
                entity.HasIndex(o => o.OrderDate);
            });

            modelBuilder.Entity<Review>(entity =>
            {
                entity.HasIndex(r => r.ProductId);
                entity.HasIndex(r => r.UserId);
            });

            modelBuilder.Entity<ShoppingCartItem>(entity =>
            {
                entity.HasIndex(sci => sci.CartId);
            });

            // Seed initial data
            SeedData(modelBuilder);
        }

        private void SeedData(ModelBuilder modelBuilder)
        {
            // Seed Categories
            modelBuilder.Entity<Category>().HasData(
                new Category { Id = 1, Name = "Smartphones", Description = "Latest smartphones from top brands", DisplayOrder = 1, ImageUrl = "/images/categories/smartphones.jpg" },
                new Category { Id = 2, Name = "Feature Phones", Description = "Basic phones with essential features", DisplayOrder = 2, ImageUrl = "/images/categories/feature-phones.jpg" },
                new Category { Id = 3, Name = "Accessories", Description = "Phone cases, chargers, and more", DisplayOrder = 3, ImageUrl = "/images/categories/accessories.jpg" },
                new Category { Id = 4, Name = "Tablets", Description = "Tablets and iPads", DisplayOrder = 4, ImageUrl = "/images/categories/tablets.jpg" }
            );

            // Seed Brands
            modelBuilder.Entity<Brand>().HasData(
                new Brand { Id = 1, Name = "Apple", Description = "Premium smartphones and devices", Country = "USA", WebsiteUrl = "https://www.apple.com" },
                new Brand { Id = 2, Name = "Samsung", Description = "Innovative technology solutions", Country = "South Korea", WebsiteUrl = "https://www.samsung.com" },
                new Brand { Id = 3, Name = "Xiaomi", Description = "High-quality at affordable prices", Country = "China", WebsiteUrl = "https://www.mi.com" },
                new Brand { Id = 4, Name = "OnePlus", Description = "Flagship killer smartphones", Country = "China", WebsiteUrl = "https://www.oneplus.com" },
                new Brand { Id = 5, Name = "Google", Description = "Pixel smartphones by Google", Country = "USA", WebsiteUrl = "https://store.google.com" },
                new Brand { Id = 6, Name = "Realme", Description = "Dare to leap", Country = "China", WebsiteUrl = "https://www.realme.com" },
                new Brand { Id = 7, Name = "Oppo", Description = "Camera phone specialists", Country = "China", WebsiteUrl = "https://www.oppo.com" },
                new Brand { Id = 8, Name = "Vivo", Description = "Camera and music phones", Country = "China", WebsiteUrl = "https://www.vivo.com" }
            );
        }
    }
}


⚙️ Step 3: Configure Program.cs



C# / Program.cs

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using MobileShop.Data;
using MobileShop.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

// Database Context
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

// Identity Configuration
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireUppercase = true;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequiredLength = 6;
    options.User.RequireUniqueEmail = true;
    options.SignIn.RequireConfirmedEmail = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
    options.AddPolicy("CustomerOnly", policy => policy.RequireRole("Customer"));
});

// Session & Shopping Cart
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// AutoMapper
builder.Services.AddAutoMapper(typeof(Program));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseSession();

app.UseAuthentication();
app.UseAuthorization();

// Seed Database
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    await DbInitializer.SeedAsync(services);
}

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();


🌱 Step 4: Create DbInitializer (Seeding)

Create file:


C# / DbInitializer.cs

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using MobileShop.Data;
using MobileShop.Models;

namespace MobileShop.Data
{
    public static class DbInitializer
    {
        public static async Task SeedAsync(IServiceProvider serviceProvider)
        {
            using var scope = serviceProvider.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
            var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
            var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();

            // Apply pending migrations
            await context.Database.MigrateAsync();

            // Seed Roles
            await SeedRolesAsync(roleManager);

            // Seed Admin User
            await SeedAdminUserAsync(userManager);

            // Seed Sample Products
            await SeedProductsAsync(context);
        }

        private static async Task SeedRolesAsync(RoleManager<IdentityRole> roleManager)
        {
            string[] roles = { "Admin", "Customer", "Manager" };

            foreach (var role in roles)
            {
                if (!await roleManager.RoleExistsAsync(role))
                {
                    await roleManager.CreateAsync(new IdentityRole(role));
                }
            }
        }

        private static async Task SeedAdminUserAsync(UserManager<ApplicationUser> userManager)
        {
            const string adminEmail = "admin@mobileshop.com";
            const string adminPassword = "Admin@123";

            var adminUser = await userManager.FindByEmailAsync(adminEmail);
            if (adminUser == null)
            {
                adminUser = new ApplicationUser
                {
                    UserName = adminEmail,
                    Email = adminEmail,
                    FirstName = "System",
                    LastName = "Administrator",
                    EmailConfirmed = true,
                    PhoneNumber = "+92-3143076781"
                };

                var result = await userManager.CreateAsync(adminUser, adminPassword);
                if (result.Succeeded)
                {
                    await userManager.AddToRoleAsync(adminUser, "Admin");
                }
            }
        }

        private static async Task SeedProductsAsync(ApplicationDbContext context)
        {
            if (await context.Products.AnyAsync()) return;

            var products = new List<Product>
            {
                new Product
                {
                    Id = 1,
                    Name = "iPhone 15 Pro Max",
                    Model = "A2849",
                    Description = "The most advanced iPhone ever with A17 Pro chip, titanium design, and 48MP camera system.",
                    ShortDescription = "A17 Pro chip, 48MP camera, titanium design",
                    OriginalPrice = 159900,
                    SalePrice = 149900,
                    StockQuantity = 50,
                    MainImageUrl = "/images/products/iphone-15-pro-max.jpg",
                    IsFeatured = true,
                    IsNewArrival = true,
                    CategoryId = 1,
                    BrandId = 1,
                    Specifications = new List<ProductSpecification>
                    {
                        new ProductSpecification { Name = "Display", Value = "6.7\" Super Retina XDR OLED", GroupName = "Display" },
                        new ProductSpecification { Name = "Processor", Value = "A17 Pro chip", GroupName = "Performance" },
                        new ProductSpecification { Name = "RAM", Value = "8GB", GroupName = "Performance" },
                        new ProductSpecification { Name = "Storage", Value = "256GB", GroupName = "Storage" },
                        new ProductSpecification { Name = "Rear Camera", Value = "48MP Main + 12MP Ultra Wide + 12MP Telephoto", GroupName = "Camera" },
                        new ProductSpecification { Name = "Front Camera", Value = "12MP TrueDepth", GroupName = "Camera" },
                        new ProductSpecification { Name = "Battery", Value = "4441 mAh", GroupName = "Battery" },
                        new ProductSpecification { Name = "OS", Value = "iOS 17", GroupName = "Software" },
                        new ProductSpecification { Name = "5G", Value = "Yes", GroupName = "Connectivity" },
                        new ProductSpecification { Name = "Weight", Value = "221g", GroupName = "Physical" }
                    }
                },
                new Product
                {
                    Id = 2,
                    Name = "Samsung Galaxy S24 Ultra",
                    Model = "SM-S928B",
                    Description = "Galaxy AI is here. With AI-powered features, 200MP camera, and S Pen functionality.",
                    ShortDescription = "Galaxy AI, 200MP camera, S Pen included",
                    OriginalPrice = 129999,
                    SalePrice = 119999,
                    StockQuantity = 45,
                    MainImageUrl = "/images/products/galaxy-s24-ultra.jpg",
                    IsFeatured = true,
                    IsBestseller = true,
                    CategoryId = 1,
                    BrandId = 2,
                    Specifications = new List<ProductSpecification>
                    {
                        new ProductSpecification { Name = "Display", Value = "6.8\" Dynamic AMOLED 2X", GroupName = "Display" },
                        new ProductSpecification { Name = "Processor", Value = "Snapdragon 8 Gen 3", GroupName = "Performance" },
                        new ProductSpecification { Name = "RAM", Value = "12GB", GroupName = "Performance" },
                        new ProductSpecification { Name = "Storage", Value = "256GB", GroupName = "Storage" },
                        new ProductSpecification { Name = "Rear Camera", Value = "200MP Main + 50MP Telephoto + 12MP Ultra Wide + 10MP Periscope", GroupName = "Camera" },
                        new ProductSpecification { Name = "Front Camera", Value = "12MP", GroupName = "Camera" },
                        new ProductSpecification { Name = "Battery", Value = "5000 mAh", GroupName = "Battery" },
                        new ProductSpecification { Name = "OS", Value = "Android 14 (One UI 6.1)", GroupName = "Software" },
                        new ProductSpecification { Name = "5G", Value = "Yes", GroupName = "Connectivity" },
                        new ProductSpecification { Name = "Weight", Value = "232g", GroupName = "Physical" }
                    }
                },
                new Product
                {
                    Id = 3,
                    Name = "Xiaomi 14 Ultra",
                    Model = "24031PN0DC",
                    Description = "Leica optics, Snapdragon 8 Gen 3, and 5300mAh battery with 90W fast charging.",
                    ShortDescription = "Leica camera, 90W fast charging, flagship performance",
                    OriginalPrice = 99999,
                    SalePrice = 89999,
                    StockQuantity = 30,
                    MainImageUrl = "/images/products/xiaomi-14-ultra.jpg",
                    IsFeatured = true,
                    IsNewArrival = true,
                    CategoryId = 1,
                    BrandId = 3,
                    Specifications = new List<ProductSpecification>
                    {
                        new ProductSpecification { Name = "Display", Value = "6.73\" AMOLED 120Hz", GroupName = "Display" },
                        new ProductSpecification { Name = "Processor", Value = "Snapdragon 8 Gen 3", GroupName = "Performance" },
                        new ProductSpecification { Name = "RAM", Value = "16GB", GroupName = "Performance" },
                        new ProductSpecification { Name = "Storage", Value = "512GB", GroupName = "Storage" },
                        new ProductSpecification { Name = "Rear Camera", Value = "50MP Main + 50MP Telephoto + 50MP Ultra Wide + 50MP Periscope", GroupName = "Camera" },
                        new ProductSpecification { Name = "Front Camera", Value = "32MP", GroupName = "Camera" },
                        new ProductSpecification { Name = "Battery", Value = "5300 mAh", GroupName = "Battery" },
                        new ProductSpecification { Name = "OS", Value = "HyperOS (Android 14)", GroupName = "Software" },
                        new ProductSpecification { Name = "5G", Value = "Yes", GroupName = "Connectivity" },
                        new ProductSpecification { Name = "Weight", Value = "219.8g", GroupName = "Physical" }
                    }
                },
                new Product
                {
                    Id = 4,
                    Name = "OnePlus 12",
                    Model = "CPH2581",
                    Description = "Smooth beyond belief with 120Hz ProXDR display and Hasselblad camera system.",
                    ShortDescription = "Hasselblad camera, 100W charging, 120Hz display",
                    OriginalPrice = 69999,
                    SalePrice = 64999,
                    StockQuantity = 40,
                    MainImageUrl = "/images/products/oneplus-12.jpg",
                    IsBestseller = true,
                    CategoryId = 1,
                    BrandId = 4,
                    Specifications = new List<ProductSpecification>
                    {
                        new ProductSpecification { Name = "Display", Value = "6.82\" LTPO AMOLED 120Hz", GroupName = "Display" },
                        new ProductSpecification { Name = "Processor", Value = "Snapdragon 8 Gen 3", GroupName = "Performance" },
                        new ProductSpecification { Name = "RAM", Value = "12GB", GroupName = "Performance" },
                        new ProductSpecification { Name = "Storage", Value = "256GB", GroupName = "Storage" },
                        new ProductSpecification { Name = "Rear Camera", Value = "50MP Main + 64MP Telephoto + 48MP Ultra Wide", GroupName = "Camera" },
                        new ProductSpecification { Name = "Front Camera", Value = "32MP", GroupName = "Camera" },
                        new ProductSpecification { Name = "Battery", Value = "5400 mAh", GroupName = "Battery" },
                        new ProductSpecification { Name = "OS", Value = "OxygenOS 14 (Android 14)", GroupName = "Software" },
                        new ProductSpecification { Name = "5G", Value = "Yes", GroupName = "Connectivity" },
                        new ProductSpecification { Name = "Weight", Value = "220g", GroupName = "Physical" }
                    }
                },
                new Product
                {
                    Id = 5,
                    Name = "Google Pixel 8 Pro",
                    Model = "GC3VE",
                    Description = "The best of Google with AI-powered features and the best camera on a Pixel.",
                    ShortDescription = "Google AI, best Pixel camera, 7 years updates",
                    OriginalPrice = 106900,
                    SalePrice = 99999,
                    StockQuantity = 25,
                    MainImageUrl = "/images/products/pixel-8-pro.jpg",
                    IsNewArrival = true,
                    CategoryId = 1,
                    BrandId = 5,
                    Specifications = new List<ProductSpecification>
                    {
                        new ProductSpecification { Name = "Display", Value = "6.7\" LTPO OLED 120Hz", GroupName = "Display" },
                        new ProductSpecification { Name = "Processor", Value = "Google Tensor G3", GroupName = "Performance" },
                        new ProductSpecification { Name = "RAM", Value = "12GB", GroupName = "Performance" },
                        new ProductSpecification { Name = "Storage", Value = "128GB", GroupName = "Storage" },
                        new ProductSpecification { Name = "Rear Camera", Value = "50MP Main + 48MP Ultra Wide + 48MP Telephoto", GroupName = "Camera" },
                        new ProductSpecification { Name = "Front Camera", Value = "10.5MP", GroupName = "Camera" },
                        new ProductSpecification { Name = "Battery", Value = "5050 mAh", GroupName = "Battery" },
                        new ProductSpecification { Name = "OS", Value = "Android 14", GroupName = "Software" },
                        new ProductSpecification { Name = "5G", Value = "Yes", GroupName = "Connectivity" },
                        new ProductSpecification { Name = "Weight", Value = "213g", GroupName = "Physical" }
                    }
                },
                new Product
                {
                    Id = 6,
                    Name = "iPhone 15",
                    Model = "A3092",
                    Description = "Dynamic Island, 48MP Main camera, and USB-C. A powerful upgrade.",
                    ShortDescription = "Dynamic Island, 48MP camera, USB-C",
                    OriginalPrice = 79900,
                    SalePrice = 74900,
                    StockQuantity = 60,
                    MainImageUrl = "/images/products/iphone-15.jpg",
                    IsBestseller = true,
                    CategoryId = 1,
                    BrandId = 1,
                    Specifications = new List<ProductSpecification>
                    {
                        new ProductSpecification { Name = "Display", Value = "6.1\" Super Retina XDR OLED", GroupName = "Display" },
                        new ProductSpecification { Name = "Processor", Value = "A16 Bionic", GroupName = "Performance" },
                        new ProductSpecification { Name = "RAM", Value = "6GB", GroupName = "Performance" },
                        new ProductSpecification { Name = "Storage", Value = "128GB", GroupName = "Storage" },
                        new ProductSpecification { Name = "Rear Camera", Value = "48MP Main + 12MP Ultra Wide", GroupName = "Camera" },
                        new ProductSpecification { Name = "Front Camera", Value = "12MP TrueDepth", GroupName = "Camera" },
                        new ProductSpecification { Name = "Battery", Value = "3349 mAh", GroupName = "Battery" },
                        new ProductSpecification { Name = "OS", Value = "iOS 17", GroupName = "Software" },
                        new ProductSpecification { Name = "5G", Value = "Yes", GroupName = "Connectivity" },
                        new ProductSpecification { Name = "Weight", Value = "171g", GroupName = "Physical" }
                    }
                },
                new Product
                {
                    Id = 7,
                    Name = "Samsung Galaxy A54 5G",
                    Model = "SM-A546E",
                    Description = "Awesome screen, awesome camera, awesome durability at a great price.",
                    ShortDescription = "120Hz AMOLED, 50MP camera, IP67 waterproof",
                    OriginalPrice = 38999,
                    SalePrice = 32999,
                    StockQuantity = 80,
                    MainImageUrl = "/images/products/galaxy-a54.jpg",
                    IsFeatured = true,
                    CategoryId = 1,
                    BrandId = 2,
                    Specifications = new List<ProductSpecification>
                    {
                        new ProductSpecification { Name = "Display", Value = "6.4\" Super AMOLED 120Hz", GroupName = "Display" },
                        new ProductSpecification { Name = "Processor", Value = "Exynos 1380", GroupName = "Performance" },
                        new ProductSpecification { Name = "RAM", Value = "8GB", GroupName = "Performance" },
                        new ProductSpecification { Name = "Storage", Value = "128GB", GroupName = "Storage" },
                        new ProductSpecification { Name = "Rear Camera", Value = "50MP Main + 12MP Ultra Wide + 5MP Macro", GroupName = "Camera" },
                        new ProductSpecification { Name = "Front Camera", Value = "32MP", GroupName = "Camera" },
                        new ProductSpecification { Name = "Battery", Value = "5000 mAh", GroupName = "Battery" },
                        new ProductSpecification { Name = "OS", Value = "Android 14 (One UI 6)", GroupName = "Software" },
                        new ProductSpecification { Name = "5G", Value = "Yes", GroupName = "Connectivity" },
                        new ProductSpecification { Name = "Weight", Value = "202g", GroupName = "Physical" }
                    }
                },
                new Product
                {
                    Id = 8,
                    Name = "Realme GT 5 Pro",
                    Model = "RMX3888",
                    Description = "Flagship performance with Snapdragon 8 Gen 3 and 5400mAh battery.",
                    ShortDescription = "Snapdragon 8 Gen 3, 100W charging, periscope camera",
                    OriginalPrice = 49999,
                    SalePrice = 44999,
                    StockQuantity = 35,
                    MainImageUrl = "/images/products/realme-gt5-pro.jpg",
                    IsNewArrival = true,
                    CategoryId = 1,
                    BrandId = 6,
                    Specifications = new List<ProductSpecification>
                    {
                        new ProductSpecification { Name = "Display", Value = "6.78\" AMOLED 144Hz", GroupName = "Display" },
                        new ProductSpecification { Name = "Processor", Value = "Snapdragon 8 Gen 3", GroupName = "Performance" },
                        new ProductSpecification { Name = "RAM", Value = "12GB", GroupName = "Performance" },
                        new ProductSpecification { Name = "Storage", Value = "256GB", GroupName = "Storage" },
                        new ProductSpecification { Name = "Rear Camera", Value = "50MP Main + 50MP Periscope + 8MP Ultra Wide", GroupName = "Camera" },
                        new ProductSpecification { Name = "Front Camera", Value = "32MP", GroupName = "Camera" },
                        new ProductSpecification { Name = "Battery", Value = "5400 mAh", GroupName = "Battery" },
                        new ProductSpecification { Name = "OS", Value = "realme UI 5.0 (Android 14)", GroupName = "Software" },
                        new ProductSpecification { Name = "5G", Value = "Yes", GroupName = "Connectivity" },
                        new ProductSpecification { Name = "Weight", Value = "218g", GroupName = "Physical" }
                    }
                }
            };

            await context.Products.AddRangeAsync(products);
            await context.SaveChangesAsync();
        }
    }
}


Configure Connection String

Open : appsettings.json
  "ConnectionStrings": {
  "DefaultConnection": "Server=.\\SQLEXPRESS;Database=Prc_MobileShop;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True;Encrypt=True"
}

Connection String Explanation

  • Server=.\SQLEXPRESS → SQL Server instance
  • Database=MobileShop → Database name
  • Trusted_Connection=True → Windows authentication
  • TrustServerCertificate=True → Avoid SSL certificate issues

What to Seed?

  • Admin Role
  • Customer Role
  • Default Admin User
  • Sample Products

🧬 Step 5: Run Migration


add-migration InitialCreate
OR dotnet tool install --global dotnet-ef dotnet ef migrations add InitialCreate

πŸ—ƒ️ Step 6: Update Database

update-database
OR
dotnet ef database update

✅ Database and tables will be created.


🧩 Database Structure Overview

Your database now supports:

  • Users (Identity)
  • Products & Categories
  • Orders & Order Items
  • Reviews
  • Wishlist
  • Shopping Cart

🧠 Pro Tips

✔ Keep models clean and simple
✔ Use navigation properties properly
✔ Use seeding for default data
✔ Always use migrations properly


🏁 Conclusion

In this part, we successfully built:

  • Complete eCommerce Models
  • ApplicationDbContext
  • Identity Integration
  • Database Seeding
  • SQL Server Database

πŸ‘‰ In Part 4, we will build:

  • Controllers
  • CRUD operations
  • Admin panel features

Comments