In diesem Tutorial erstellen wir eine Blazor Server-Anwendung, die über NTi EF Core mit einer DB2 for i-Datenbank interagiert. Wir implementieren ein einfaches CRUD zur Datenbearbeitung.
Wir verwenden ein Beispiel zur Verwaltung von Produkten, Kategorien und Bestellungen:
Schritt 1 – Erstellung und Konfiguration des Projekts
Erstellen Sie ein neues .NET-Projekt und wählen Sie das Projekttemplate blazor Web App. Wählen Sie in den Projektoptionen den Server Interactive Render Mode und stellen Sie sicher, dass Sie .NET 8.0 auswählen.
Fügen Sie die notwendigen Pakete hinzu:
dotnet add package Aumerial.Data.NTi
dotnet add package Aumerial.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design
Fügen Sie die Verbindungszeichenfolge in appsettings.json
hinzu und geben Sie das Standardschema an, in dem alle erstellten Entitäten platziert werden:
{
"ConnectionStrings": {
"DefaultConnection": "server=myserver;user=myuser;password=mypassword;database=mydb"
}
}
Schritt 2 – Definition der Entitäten
Erstellen Sie einen Ordner Models, um Ihre Entitäten zu organisieren, und fügen Sie die folgenden Klassen hinzu, um Ihre Daten zu modellieren.
Category.cs
Eine Kategorie kann mehrere Produkte enthalten.
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Product> Products { get; set; }
}
Product.cs
Ein Produkt gehört zu einer Kategorie und kann mit mehreren Bestellungen verknüpft sein.
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
Eine Bestellung kann mehrere Produkte enthalten.
public class Order
{
public int Id { get; set; }
public DateTime OrderDate { get; set; }
public DateTime? DeliveryDate { get; set; }
public decimal TotalAmount { get; set; }
}
Schritt 3 – Konfiguration von DbContext
Fügen Sie eine Klasse AppDbContext
hinzu, die von DbContext
erbt, um die Entitäten und deren Beziehungen zu verwalten.
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)
{
}
}
Schritt 4 – Konfiguration in Program.cs
Damit die Anwendung DbContext
verwenden kann, müssen Sie ihn in Program.cs konfigurieren und als Dienst über Dependency Injection für Ihre Blazor-Komponenten registrieren.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNti(connectionString));
- AddDbContext wird für die meisten Blazor Server-Anwendungen empfohlen. Der
DbContext
wird mit einer Scoped-Lebensdauer instanziiert, was bedeutet, dass er bei jeder Benutzeranfrage neu erstellt wird. - AddDbContextFactory wird in Szenarien verwendet, in denen der
DbContext
dynamisch erstellt werden muss, wie z. B. bei Hintergrundaufgaben oder Multithread-Verarbeitung.
Schritt 5 – Erstellung und Verwaltung von Migrationen
Erzeugen Sie eine initiale Migration, um Ihre Entitäten mit der Datenbank zu synchronisieren. Dieser Befehl erstellt eine Datei im Ordner Migrations, die die SQL-Anweisungen zum Erstellen Ihrer Tabellen enthält:
dotnet ef migrations add InitialCreate
Wenden Sie anschließend die Migration an, um die Datenbank zu aktualisieren und die Tabellen zu erstellen:
dotnet ef database update
Um eine neue Tabelle hinzuzufügen oder eine bestehende Tabelle zu ändern, gilt das gleiche Prinzip: Erstellen Sie Ihre Entitäten, fügen Sie sie in AppDbContext
hinzu und erzeugen Sie eine neue Migration, um die neue Tabelle zu berücksichtigen.
dotnet ef migrations add newEntity
Aktualisieren Sie die Datenbank, um die neue Tabelle einzubeziehen:
dotnet ef database update
Wenn Sie einen Fehler gemacht haben, können Sie die letzte Migration löschen, bevor sie angewendet wird:
dotnet ef migrations remove
Wenn Sie zu einer früheren Version der Datenbank zurückkehren möchten, können Sie den Namen der Migration direkt angeben:
dotnet ef database update <NomMigrationPrécédente>
Schritt 7 – Hinzufügen eines initialen Datensatzes
Fügen Sie nach dem Anwenden der Migrationen einen Datensatz in die Datenbank ein. Machen Sie dies in program.cs nach der Registrierung der Dienste:
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();
}
Schritt 8 – Generierung der CRUD-Seiten
Fügen Sie automatisch die CRUD-Seiten für die Entitäten hinzu:
Rechtsklick auf den Ordner Pages > Hinzufügen > Razor-Komponenten mit EF (CRUD).
Für das CRUD Produkte wählen Sie Product
als Modell und AppDbContext
als Kontext aus.
Schritt 9 – Hinzufügen eines Feldes für den Bild-Upload (BLOB)
Wir fügen ein Image-Feld vom Typ byte[]
hinzu, um die Bilddaten in der Datenbank zu speichern.
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; }
// Neues Feld für das Bild
[Column(TypeName = "BLOB(1M)"), DataType(DataType.Upload)]
public byte[] Image { get; set; }
}
Wir erzeugen eine Migration, um das neue Feld zur Tabelle products
hinzuzufügen, und aktualisieren anschließend die Datenbank.
dotnet ef migrations add AddProductImage
dotnet ef database update
Anschließend müssen die Komponenten EditProduct
und CreateProduct
angepasst werden, um ein Feld für den Bild-Upload hinzuzufügen:
<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>Aktuelles Bild :</p>
<img src="data:image/jpeg;base64,@Convert.ToBase64String(Product.Image)"
style="max-width: 200px; max-height: 200px;" />
}
else
{
<p>Kein Bild verfügbar</p>
}
</div>
Und die Methode zur Handhabung des Uploads:
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();
}
}
Visualisierung des erzeugten CRUD auf der Produkt-Index-Seite:
Quentin Destrade