Implement initial product management with Entity Framework Core #3

This commit is contained in:
Marek Lesko
2025-07-27 16:03:55 +00:00
parent 5f921e5a2c
commit e969008873
9 changed files with 272 additions and 22 deletions

View File

@@ -12,6 +12,11 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.18" NoWarn="NU1605" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.18" NoWarn="NU1605" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.7" />
<PackageReference Include="Microsoft.Identity.Web" Version="3.10.0" />
<PackageReference Include="Microsoft.Identity.Web.DownstreamApi" Version="3.10.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />

View File

@@ -0,0 +1,61 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Api.Models;
namespace Api.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
private readonly AppDbContext _context;
public ProductController(AppDbContext context)
{
_context = context;
}
// GET: api/Product
[HttpGet]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
return await _context.Products.ToListAsync();
}
// POST: api/Product
[HttpPost]
public async Task<ActionResult<Product>> PostProduct([FromBody] Product product)
{
_context.Products.Add(product);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetProducts), new { id = product.Id }, product);
}
// PUT: api/Product/{id}
[HttpPut("{id}")]
public async Task<IActionResult> PutProduct(int id, [FromBody] Product product)
{
if (id != product.Id)
{
return BadRequest();
}
_context.Entry(product).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await _context.Products.AnyAsync(e => e.Id == id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
}
}

View File

@@ -0,0 +1,56 @@
// <auto-generated />
using Api.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Api.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250727154636_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Api.Models.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.HasColumnType("nvarchar(max)");
b.Property<decimal>("Price")
.HasColumnType("decimal(18,2)");
b.HasKey("Id");
b.ToTable("Products");
b.HasData(
new
{
Id = 1,
Name = "Sample Product",
Price = 9.99m
});
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Api.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
});
migrationBuilder.InsertData(
table: "Products",
columns: new[] { "Id", "Name", "Price" },
values: new object[] { 1, "Sample Product", 9.99m });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Products");
}
}
}

View File

@@ -0,0 +1,53 @@
// <auto-generated />
using Api.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Api.Migrations
{
[DbContext(typeof(AppDbContext))]
partial class AppDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Api.Models.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.HasColumnType("nvarchar(max)");
b.Property<decimal>("Price")
.HasColumnType("decimal(18,2)");
b.HasKey("Id");
b.ToTable("Products");
b.HasData(
new
{
Id = 1,
Name = "Sample Product",
Price = 9.99m
});
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
namespace Api.Models
{
public class Product
{
public int Id { get; set; }
public string? Name { get; set; }
public decimal Price { get; set; }
}
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Seed data
modelBuilder.Entity<Product>().HasData(
new Product { Id = 1, Name = "Sample Product", Price = 9.99M }
);
}
}
}

View File

@@ -6,17 +6,19 @@ using Microsoft.Identity.Web.Resource;
namespace Api
{
public class Program
using Microsoft.EntityFrameworkCore;
using Api.Models;
public static class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
//builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
// .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllers();
// Add DbContext with SQL Server
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
@@ -24,19 +26,14 @@ namespace Api
var app = builder.Build();
// Configure the HTTP request pipeline.
// if (app.Environment.IsDevelopment())
// {
app.UseSwagger();
app.UseSwaggerUI();
// }
app.UseSwagger();
app.UseSwaggerUI();
if (!app.Environment.IsDevelopment())
{
app.UseHttpsRedirection();
}
// app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@@ -4,5 +4,8 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=localhost,1433;Database=CentrumDb;User=sa;Password=P@ssw0rd;TrustServerCertificate=True;"
}
}