Perfect! Now that your database is ready with Customers and Orders, we can move to the backend setup. Since this is a mini full-stack practice project, I recommend using ASP.NET Core Web API instead of a console app. This will mimic a real interview scenario more closely:
- Open Visual Studio (or VSCode with C# extension + .NET SDK installed).
- New Project → ASP.NET Core Web API
- Project name:
MiniFullStackApi - .NET version: latest LTS (for now, 7.0 or 8.0)
- Make sure “Use controllers” is checked (default) and “Enable OpenAPI / Swagger” is checked. This is optional but will help test endpoints easily.
- Click Create.
In appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=YOUR_SERVER_NAME;Database=MyFullStackDB;Trusted_Connection=True;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}- Replace
YOUR_SERVER_NAMEwith your SQL Server instance (check in SSMS top-left). Trusted_Connection=Truemeans it will use your Windows credentials.
- In Package Manager Console:
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.Tools- These allow your API to talk to SQL Server using Entity Framework Core.
- Create a folder
Models:
// Models/Customer.cs
using System.Collections.Generic;
namespace MiniFullStackApi.Models;
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Region { get; set; }
public ICollection<Order> Orders { get; set; }
}
// Models/Order.cs
namespace MiniFullStackApi.Models;
public class Order
{
public int Id { get; set; }
public string Product { get; set; }
public double Amount { get; set; }
public int CustomerId { get; set; } // foreign key
public Customer Customer { get; set; } // navigation property
}Create folder Data:
// Data/AppDbContext.cs
using Microsoft.EntityFrameworkCore;
using MiniFullStackApi.Models;
using System.Collections.Generic;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options) { }
public DbSet<Customer> Customers { get; set; }
public DbSet<Order> Orders { get; set; }
}Good — now we move to the DbContext, which is the central piece of EF. Think of it as the bridge between your C# models and the database tables.
I’ll stay focused only on the DbContext step as you asked.
Project structure should start looking like this:
MiniFullStackApi
│
├── Controllers
├── Data
│
├── Models
│ Customer.cs
│ Order.cs
│
├── Program.cs
└── appsettings.json
Inside Data, create a new file:
AppDbContext.cs
At the top of the file you need:
using Microsoft.EntityFrameworkCore;
using MiniFullStackApi.Models;Explanation:
Microsoft.EntityFrameworkCore→ providesDbContext,DbSet, etc.MiniFullStackApi.Models→ so EF can seeCustomerandOrder.
Your file should look like this:
using Microsoft.EntityFrameworkCore;
using MiniFullStackApi.Models;
namespace MiniFullStackApi.Data;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
public DbSet<Customer> Customers { get; set; }
public DbSet<Order> Orders { get; set; }
}public class AppDbContext : DbContextThis tells EF:
"This class manages database access."
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}This allows ASP.NET to inject configuration, including:
- connection string
- SQL Server provider
- logging
- caching
You normally do not modify this.
public DbSet<Customer> Customers { get; set; }
public DbSet<Order> Orders { get; set; }These represent tables.
| C# | Database |
|---|---|
| DbSet | Customers table |
| DbSet | Orders table |
So EF now knows:
Customer -> Customers table
Order -> Orders table
With this setup you can write things like:
_context.Customers.ToList();or
_context.Orders
.Where(o => o.Amount > 100)
.ToList();EF converts this to SQL automatically.
SQL Server
↑
│
AppDbContext
│
├── DbSet<Customer>
│
└── DbSet<Order>
│
│
Models
Once the DbContext file exists, the next step is to register it in Program.cs, so the application knows:
- which database to use
- which connection string
- that EF is available for dependency injection.
That step is small but important.
Then in Program.cs:
using Microsoft.EntityFrameworkCore; // required for DbContext and UseSqlServer()
using MiniFullStackApi.Models; // or whatever namespace your AppDbContext is in
....
// Configure EF Core with SQL Server
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));You can create controllers manually or use scaffolding. For practice, let's create CustomerController manually:
// Controllers/CustomerController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MiniFullStackApi.Data;
using MiniFullStackApi.Models;
[ApiController]
[Route("api/[controller]")]
public class CustomersController : ControllerBase
{
private readonly AppDbContext _context;
public CustomersController(AppDbContext context)
{
_context = context;
}
[HttpGet]
public async Task<IEnumerable<Customer>> GetAll()
{
return await _context.Customers.Include(c => c.Orders).ToListAsync();
}
[HttpGet("{id}")]
public async Task<ActionResult<Customer>> Get(int id)
{
var customer = await _context.Customers.Include(c => c.Orders)
.FirstOrDefaultAsync(c => c.Id == id);
if (customer == null) return NotFound();
return customer;
}
[HttpPost]
public async Task<ActionResult<Customer>> Create(Customer customer)
{
_context.Customers.Add(customer);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(Get), new { id = customer.Id }, customer);
}
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, Customer customer)
{
if (id != customer.Id) return BadRequest();
_context.Entry(customer).State = EntityState.Modified;
await _context.SaveChangesAsync();
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
var customer = await _context.Customers.FindAsync(id);
if (customer == null) return NotFound();
_context.Customers.Remove(customer);
await _context.SaveChangesAsync();
return NoContent();
}
}✅ At this point, your backend can:
- Perform CRUD operations on Customers
- Fetch Orders via navigation property for a customer
- Be tested via Swagger UI (
https://localhost:5001/swagger)
Next steps after this:
- OrdersController with CRUD, filtering, sorting, grouping, and aggregation endpoints.
- React front-end to consume these APIs, implement forms, validations, and display lists with filtering and sorting.
Yes — using .NET 8 SDK (8.0.419) is the right move. Most likely you will be able to install Entity Framework Core packages via the NuGet Package Manager in Visual Studio without needing admin permissions, because:
- VS NuGet installs per user by default – it doesn’t require admin if you don’t try to install packages globally.
- EF Core fully supports .NET 8, so no SDK mismatch.
- You can target net8.0 in your project and all EF Core packages for .NET 8 will be compatible.
-
Set project to .NET 8
- Right-click project → Properties → Target Framework →
.NET 8.0
- Right-click project → Properties → Target Framework →
-
Open NuGet Package Manager
- Tools → NuGet Package Manager → Manage NuGet Packages for Solution…
-
Install EF Core packages (latest stable 8.x version)
Microsoft.EntityFrameworkCore(core)Microsoft.EntityFrameworkCore.SqlServer(for SQL Server)- Optional:
Microsoft.EntityFrameworkCore.Tools(for migrations)
-
Check your project file (.csproj) – it should now include:
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>💡 Tip: If NuGet restore fails again, make sure Package Source is set to nuget.org and that you’re not behind a proxy that blocks downloads.