Creare un'Applicazione Blazor Server con Entity Framework Core 8

In questo tutorial, creeremo un'applicazione Blazor Server che interagisce con un database DB2 for i tramite NTi EF Core. Implementeremo un CRUD semplice per manipolare i dati.

immagine illustrativa dell'articolo “Creare un'Applicazione Blazor Server con Entity Framework Core 8”

In questo tutorial, creeremo un'applicazione Blazor Server che interagisce con un database DB2 for i tramite NTi EF Core. Implementeremo un CRUD semplice per manipolare i dati.

Useremo un esempio di gestione di prodotti, categorie e ordini:

Passo 1 - Creazione e Configurazione del Progetto

Create un nuovo progetto .NET e scegliete il modello di progetto blazor Web App. Nelle opzioni di configurazione del progetto, selezionate Server Interactive Render Mode e assicuratevi di scegliere .NET 8.0.

Aggiungete i pacchetti necessari:

dotnet add package Aumerial.Data.NTi
dotnet add package Aumerial.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design

Aggiungete la stringa di connessione in appsettings.json e specificate lo schema predefinito in cui saranno collocate tutte le entità create:

{
    "ConnectionStrings": {
        "DefaultConnection": "server=myserver;user=myuser;password=mypassword;database=mydb"
    }
}

Passo 2 - Definizione delle Entità

Create una cartella Models per organizzare le vostre entità e aggiungete le seguenti classi per modellare i vostri dati.

  • Category.cs

Una categoria può contenere più prodotti.

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Product> Products { get; set; }
}
  • Product.cs

Un prodotto appartiene a una categoria e può essere collegato a più ordini.

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string description { get; set; }
    public decimal Price { get; set; }
    public int stockQuantity { get; set; }
    public decimal Weight { get; set; } 
    public bool IsAvailable { get; set; }

    public int CategoryId { get; set; }
    public Category Category { get; set; }
}
  • Order.cs

Un ordine può contenere più prodotti.

public class Order
{
    public int Id { get; set; }
    public DateTime OrderDate { get; set; }
    public DateTime? DeliveryDate { get; set; }
    public decimal TotalAmount { get; set; } 

}

Passo 3 - Configurazione di DbContext

Aggiungete una classe AppDbContext che eredita da DbContext, per gestire le entità e le loro relazioni.

using Microsoft.EntityFrameworkCore;

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

    public DbSet<Product> Products { get; set; }
    public DbSet<Category> Categories { get; set; }
    public DbSet<Order> Orders { get; set; }

     protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
       
    }
}

Passo 4 - Configurazione in Program.cs

Per permettere all’applicazione di utilizzare DbContext, dovete configurarlo in Program.cs e registrarlo come servizio tramite dependency injection per i vostri componenti Blazor.

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseNti(connectionString));
  • AddDbContext è consigliato per la maggior parte delle applicazioni Blazor Server. Il DbContext viene istanziato con una durata Scoped, il che significa che viene ricreato ad ogni richiesta utente.
  • AddDbContextFactory è usato in scenari dove il DbContext deve essere creato dinamicamente, come nei task in background o in elaborazioni multi-thread.

Passo 5 - Creazione e gestione delle Migrazioni

Generate una migrazione iniziale per sincronizzare le vostre entità con il database. Questo comando creerà un file nella cartella Migrations contenente le istruzioni SQL per creare le vostre tabelle:

dotnet ef migrations add InitialCreate

Applicate quindi la migrazione per aggiornare il database e creare le tabelle:

dotnet ef database update

Schema delle tabelle DB2 for i in ACS (QDEFTUTO)

Per aggiungere una nuova tabella o modificare una tabella esistente, vale lo stesso principio. Create le vostre entità, aggiungetele in AppDbContext e generate una nuova migrazione per includere la nuova tabella:

dotnet ef migrations add newEntity

Aggiornate il database per includere la nuova tabella:

dotnet ef database update

Se avete commesso un errore, potete eliminare l’ultima migrazione prima della sua applicazione:

dotnet ef migrations remove

Se desiderate tornare a una versione precedente del database, potete specificare direttamente il nome della migrazione.

dotnet ef database update <NomMigrationPrécédente>

Passo 6 - Aggiunta del set di dati iniziale

Aggiungete un set di dati nel database dopo l’applicazione delle migrazioni. Fate questo in program.cs dopo la registrazione dei servizi:


using (var scope = app.Services.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();

    var categories = new List<Category>
        {
            new Category { Name = "Electronics" },
            new Category { Name = "Books" },
            new Category { Name = "Home Appliances" },
            new Category { Name = "Fashion" },
            new Category { Name = "Toys" }
        };

    context.Categories.AddRange(categories);


    var products = new List<Product>
        {
            new Product { Name = "Smartphone", Price = 500, stockQuantity = 10, Category = categories[0], IsAvailable = true },
            new Product { Name = "Laptop", Price = 1200, stockQuantity = 5, Category = categories[0], IsAvailable = true },
            new Product { Name = "Washing Machine", Price = 300, stockQuantity = 8, Category = categories[2], IsAvailable = true },
            new Product { Name = "T-Shirt", Price = 20, stockQuantity = 50, Category = categories[3], IsAvailable = true },
            new Product { Name = "Children's Book", Price = 15, stockQuantity = 100, Category = categories[1], IsAvailable = true },
            new Product { Name = "Toy Car", Price = 30, stockQuantity = 20, Category = categories[4], IsAvailable = true },
            new Product { Name = "Microwave Oven", Price = 250, stockQuantity = 6, Category = categories[2], IsAvailable = true },
            new Product { Name = "Jeans", Price = 40, stockQuantity = 30, Category = categories[3], IsAvailable = true }
        };

    context.Products.AddRange(products);


    var orders = new List<Order>
        {
            new Order { OrderDate = DateTime.Now.AddDays(-10), DeliveryDate = DateTime.Now.AddDays(-7), TotalAmount = 750 },
            new Order { OrderDate = DateTime.Now.AddDays(-5), DeliveryDate = DateTime.Now.AddDays(-3), TotalAmount = 600 },
            new Order { OrderDate = DateTime.Now.AddDays(-2), DeliveryDate = null, TotalAmount = 290 }
        };

    context.Orders.AddRange(orders);


    var orderProducts = new List<OrderProduct>
        {
            new OrderProduct { Order = orders[0], Product = products[0] },
            new OrderProduct { Order = orders[0], Product = products[1] },
            new OrderProduct { Order = orders[0], Product = products[3] },

            new OrderProduct { Order = orders[1], Product = products[4] },
            new OrderProduct { Order = orders[1], Product = products[5] },
            new OrderProduct { Order = orders[1], Product = products[6] },

            new OrderProduct { Order = orders[2], Product = products[2] },
            new OrderProduct { Order = orders[2], Product = products[7] }
        };

    context.OrderProducts.AddRange(orderProducts);


    context.SaveChanges();
}

Passo 7 - Generazione delle Pagine CRUD

Aggiungete automaticamente le pagine CRUD per le entità:

Click destro sulla cartella Pages > Aggiungi > Componenti Razor con EF (CRUD).

Per il CRUD Prodotti, selezionate Product come modello e AppDbContext come contesto.

Passo 8 - Aggiunta di un campo per l’UPLOAD di un’immagine (BLOB)

Aggiungeremo un campo Image di tipo byte[] per memorizzare i dati dell’immagine nel database.

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public int StockQuantity { get; set; }
    public decimal Weight { get; set; }
    public bool IsAvailable { get; set; }

    public int CategoryId { get; set; }
    public Category Category { get; set; }

    // Nuovo campo per l’immagine
    
    [Column(TypeName = "BLOB(1M)"), DataType(DataType.Upload)]
    public byte[] Image { get; set; }
}

Generiamo una migrazione per aggiungere il nuovo campo alla tabella products, quindi aggiorniamo il database.

dotnet ef migrations add AddProductImage
dotnet ef database update

Successivamente, è necessario modificare i componenti EditProduct e CreateProduct per aggiungere un campo per il caricamento dell’immagine:

<div class="mb-3">
    <label for="image" class="form-label">Image:</label>
    <InputFile id="image" OnChange="UploadFile" class="form-control" />
    @if (Product?.Image != null && Product.Image.Length > 0)
    {
        <p>Immagine attuale :</p>
        <img src="data:image/jpeg;base64,@Convert.ToBase64String(Product.Image)" 
             style="max-width: 200px; max-height: 200px;" />
    }
    else
    {
        <p>Nessuna immagine disponibile</p>
    }
</div>

E il metodo per gestire il caricamento:

    private async Task UploadFile(InputFileChangeEventArgs e)
    {
        var file = e.File;

        if (file != null)
        {
            using var memoryStream = new MemoryStream();
            await file.OpenReadStream().CopyToAsync(memoryStream);
            Product.Image = memoryStream.ToArray();
        }
    }

Visuale del CRUD ottenuto nella pagina indice dei prodotti:

Pagina CRUD Prodotti in applicazione Blazor Server.


Quentin Destrade