Eine vollständige .NET-Anwendung mit Lino erstellen: Schritt-für-Schritt-Anleitung

Dieses Thema bietet eine praktische Schritt-fΓΌr-Schritt-Anleitung zur Verwendung Lino CLI als Hauptwerkzeug beim Aufbau eines Projekts: von der Installation und Erstkonfiguration ΓΌber die Generierung von Diensten, Modulen und EntitΓ€ten bis hin zu erweiterten Funktionen wie Ereignissen, Background Jobs, Migrationen, der Erstellung von Docker-Images und der Versionierung.

Ziel ist es, auf integrierte Weise zu zeigen, wie CLI-Commands in den realen Entwicklungsablauf passen – sie nicht nur aufzulisten, sondern auch zu erklΓ€ren, warum jede Auswahl getroffen wird, was automatisch generiert wird und welche Auswirkungen sie auf die Architektur hat.

Auch wenn fΓΌr jeden Befehl bereits eine spezifische Dokumentation vorhanden ist, sehen Sie hier den Vorgang Ende-zu-Ende – eine wiederholbare Roadmap, die Stunden repetitiver Arbeit erspart und dabei hilft, konsistenten, testbaren Code aufrechtzuerhalten.

Im gesamten Leitfaden werden wir technische Konzepte erlΓ€utern, die von Lino angewendet werden (z. B.: CQRS, TypedResults, Source Generators, Outbox Pattern) zeigen wir Beispielbefehle und weisen auf bewΓ€hrte Vorgehensweisen fΓΌr Versionierung, Bereitstellung und kontinuierliche Integration hin.

Verwenden Sie diese Roadmap als Lernsequenz: Verstehen Sie zunΓ€chst die Struktur, modellieren Sie dann die DomΓ€ne und generieren Sie erst dann APIs, Seiten, Ereignisse und Bereitstellungsartefakte. Dies reduziert die Nacharbeit und sorgt dafΓΌr, dass der generierte Code mit dem Systemdesign ΓΌbereinstimmt.

Installieren und Konfigurieren von Lino CLI

Der erste Schritt, um mit der Arbeit zu beginnen Lino CLI besteht darin, das Tool in Ihrer Entwicklungsumgebung zu installieren. Es wird als verteilt globales Dotnet-Tool, was bedeutet, dass es fΓΌr jedes.NET-Projekt auf Ihrem Computer verfΓΌgbar ist. Vergewissern Sie sich vor der Installation, dass das fΓΌr die aktuellen Vorlagen erforderliche .NET SDK verfΓΌgbar ist, das Terminal dotnet ausfΓΌhren kann und sich das globale .NET-Tools-Verzeichnis im PATH des Systems befindet.

Schritt 1: Installation

Um Lino CLI zu installieren (oder zu aktualisieren), fΓΌhren Sie den folgenden Befehl im Terminal aus:

dotnet tool install --global Tolitech.Lino

Wichtige Hinweise:

  • Wenn bereits eine Version installiert ist, kΓΆnnen Sie diese verwenden dotnet tool update --global Tolitech.Lino zu aktualisieren.
  • Stellen Sie sicher, dass sich das globale .NET-Tools-Verzeichnis im PATH des Systems befindet, damit der Befehl lino korrekt funktioniert.

Schritt 2: Sprache konfigurieren

Nach der Installation wird empfohlen, die Sprache (oder Kultur) zu konfigurieren, die CLI in Nachrichten, Eingabeaufforderungen und Protokollen verwendet:

lino preferences culture set

Sie werden aufgefordert, eine der verfΓΌgbaren Sprachen auszuwΓ€hlen. Diese Einstellung stellt sicher, dass alle Anweisungen und Eingabeaufforderungen einheitlich in der gewΓΌnschten Sprache angezeigt werden. Diese Einstellung Γ€ndert CLI lokalisierte Nachrichten, Eingabeaufforderungen und Anleitungen; EntitΓ€ten, Dienste, Module oder GeschΓ€ftsbegriffe, die im Projekt generiert wurden, werden nicht umbenannt.

Schritt 3: Authentifizierung und Registrierung

Um auf alle Lino-Funktionen zuzugreifen, einschließlich erweiterter Vorlagen, Docker-Image-Verâffentlichung und Integrationen mit externen Diensten, müssen Sie authentifiziert sein.

- Wenn Sie noch nicht registriert sind, registrieren Sie sich mit dem Befehl:

lino user register

- Wenn Sie bereits registriert sind, melden Sie sich an mit:

lino auth login

Was geschieht: CLI speichert ein Authentifizierungs-token lokal, sodass Sie Commands ausfΓΌhren kΓΆnnen, die Zugriff auf geschΓΌtzte Ressourcen erfordern, ohne sich bei jeder Verwendung anmelden zu mΓΌssen. Halten Sie dieses Token privat und vermeiden Sie die gemeinsame Nutzung desselben Benutzerprofils zwischen verschiedenen Entwicklern, CI-Agenten oder Maschinen.

Schritt 4: Verifizierung

Um zu bestΓ€tigen, dass Installation und Authentifizierung erfolgreich waren, fΓΌhren Sie Folgendes aus:

lino --version

Wenn der Befehl die installierte Version zurΓΌckgibt, kΓΆnnen Sie Lino CLI in Ihren Projekten verwenden.

Erstellen des MyApp-Projekts

In diesem Schritt erstellen wir die anfΓ€ngliche Struktur des Projekts mithilfe von Lino CLI. Dieses Projekt dient als Grundlage fΓΌr die Demonstration der Erstellung von Diensten, Modulen, Frontends und der Integration aller Ereignisse. Ein Lino-Projekt ist nicht nur ein Ordner mit einer LΓΆsung: Es definiert Konventionen fΓΌr Dienstgrenzen, gemeinsam genutzte Bibliotheken, Aspire-Host, Frontend-Framework, Tests, Paketverwaltung, Analysatoren und Konfigurationen, die die nΓ€chsten Commands wiederverwenden.

Schritt 1: AusfΓΌhren des Befehls β€žcreateβ€œ.

Um ein neues Projekt zu erstellen, fΓΌhren Sie den folgenden Befehl im Terminal aus:

lino project new

CLI fΓΌhrt Sie Schritt fΓΌr Schritt und fragt nach Informationen wie:

  • Projektname: wir werden es nutzen MyApp, aber Sie kΓΆnnen einen beliebigen Namen wΓ€hlen;
  • ZusΓ€tzliche Funktionen: Code-Analysatoren, verteiltes Caching, asynchrone EreignisunterstΓΌtzung usw.

Schritt 2: Wesentliche Funktionen konfigurieren

FΓΌr dieses Projekt empfehlen wir, die folgenden Funktionen von Anfang an zu aktivieren:

  • Code-Analysatoren: um sicherzustellen, dass der Kodex bewΓ€hrten Praktiken und einheitlichen Standards folgt und so hΓ€ufige Implementierungsfehler verhindert wird;
  • Verteilter Cache: verbessert die Anwendungsleistung in Szenarien mit mehreren Diensten und vermeidet unnΓΆtige Datenbankabfragen;
  • Asynchrone Kommunikation: ermΓΆglicht die Verwendung von Ereignissen und Warteschlangen fΓΌr die Integration zwischen Diensten und gewΓ€hrleistet so Skalierbarkeit und Entkopplung.

Es ist wichtig, alle diese Optionen in diesem Projekt zu aktivieren, da wir mehrere Dienste erstellen werden, die ΓΌber Integrationsereignisse kommunizieren. Dadurch erfahren Sie, wie Sie modulare und verteilte Systeme mit Lino strukturieren.

Schritt 3: Generierte Struktur

Nach der AusfΓΌhrung des Befehls und der Konfiguration der Ressourcen generiert CLI die anfΓ€ngliche Projektstruktur. Es umfasst:

  • Ordner β€žDienste und Moduleβ€œ;
  • Frontend-Vorlagen (falls zutreffend);
  • AnfΓ€ngliche Cache-Einstellungen, Ereignisse und Integrationen;
  • LΓΆsungsdateien (.slnx) und Projektdateien (.csproj) bereit zur Kompilierung.

Jetzt ist Ihr Projekt MeineApp bereit, die Dienste, Module, EntitΓ€ten und das Frontend zu empfangen, die wir in den nΓ€chsten Schritten konfigurieren werden. Bevor Sie fortfahren, ΓΆffnen Sie die generierte LΓΆsung und fΓΌhren Sie sie aus dotnet build um zu bestΓ€tigen, dass Referenzen, Source Generators, Vorlagen, Projektdateien und Erstkonfiguration kohΓ€rent sind.

HinzufΓΌgen der Backoffice-Webanwendung

Ein Gesamtsystem benâtigt typischerweise mindestens eine Webanwendung zum Betrieb der DomÀne. In dieser Anleitung wird die Anwendung aufgerufen Backoffice und stellt eine interne Schnittstelle für Administratoren, Manager oder operative Benutzer zur Überwachung von Produkten, Kategorien, BestÀnden, Salesn und anderen Systeminformationen dar.

Die Webanwendung ersetzt keine DomΓ€nendienste. Sie fungiert als visueller Einstiegspunkt, um APIs zu nutzen, Commands auszulΓΆsen, Queries abzufragen und Bildschirme anzuzeigen, die mit den bereits in den Diensten modellierten Regeln ΓΌbereinstimmen.

Schritt 1: AusfΓΌhren des Befehls β€žcreateβ€œ.

Um dem Projekt eine neue Webanwendung hinzuzufΓΌgen, verwenden Sie:

lino web-app new

Der Alias lino webapp new ist ebenfalls verfΓΌgbar, um die Eingabe zu erleichtern. Geben Sie wΓ€hrend der AusfΓΌhrung einen klaren Namen fΓΌr die Webanwendung an; in diesem Beispiel verwenden wir Backoffice.

lino web-app new --name Backoffice

Schritt 2: Verstehen der generierten Struktur

Am Ende des Prozesses erstellt Lino die Anfangsstruktur der Web App unter src/WebApps/<WebAppName>. FΓΌr eine Blazor-Anwendung kann die Struktur Server-/Client-Projekte, gemeinsame Ressourcen, Lokalisierungsdateien, Clients fΓΌr den Zugriff auf APIs und Konventionen enthalten, die spΓ€ter von lino page new verwendet werden.

  • Ordner fΓΌr Seiten, Komponenten, Layouts, Dienste und Anwendungsressourcen;
  • HTTP-Clients und -VertrΓ€ge, die fΓΌr die Nutzung von APIs erforderlich sind, die von Projektdiensten bereitgestellt werden;
  • Lokalisierungsressourcen und anfΓ€ngliche Vorlagen, die vom Web-Erlebnis verwendet werden;
  • Client/Server-Projekte, wenn die Art der Anwendung diese Trennung erfordert;
  • Routen-, Navigations- und Integrationskonventionen, die bei der Seitengenerierung wiederverwendet werden;
  • Integrationspunkte mit Authentifizierung und Autorisierung, wenn die Authentifizierungsfunktion zum Projekt hinzugefΓΌgt wird.

Schritt 3: Wann soll die Web-App im Flow erstellt werden?

Wenn bereits feststeht, dass das System eine Blazor-OberflΓ€che haben wird, erstellen Sie die Web App frΓΌh, direkt nach der Projekterstellung. So sind die spΓ€ter generierten Services, Module, EntitΓ€ten, APIs und Seiten bereits auf die Webanwendung ausgerichtet, die sie konsumieren wird.

Dieser Ablauf ist besonders nΓΌtzlich, weil spΓ€ter erstellte Services auch typisierte Projekte Api.Contracts und Api.Client erzeugen, die vom Blazor-Projekt konsumiert werden. Wenn die Web App von Anfang an vorhanden ist, lΓ€sst sich der gesamte Weg einfacher validieren: DomΓ€ne, API, Contracts, HttpClient und Bildschirm.

Wichtige Hinweise

  • Das Backoffice muss die Daten ΓΌber die generierten APIs nutzen und dabei die GeschΓ€ftslogik in den richtigen Diensten und Modulen aufrechterhalten.
  • Bevor Sie Verwaltungsseiten freigeben, ΓΌberprΓΌfen Sie Authentifizierung, Autorisierung, Rollen, Berechtigungen und Zugriffsrichtlinien.
  • Sie kΓΆnnen mehrere Webanwendungen erstellen, zum Beispiel eine Backoffice intern und a Site ΓΆffentlich, wenn Zielgruppen, Berechtigungen, Bereitstellungen oder Verantwortlichkeiten unterschiedlich sind.
  • Vermeiden Sie die Vermischung ΓΆffentlicher und administrativer AblΓ€ufe in derselben Web-App, wenn dies die Sicherheit, Navigation, Bereitstellung oder Teamverantwortung erschwert.

Nachdem die Webanwendung erstellt wurde, kann der Leitfaden mit den Diensten und Modulen fortfahren, die die von dieser Schnittstelle genutzten Daten und GeschΓ€ftsregeln bereitstellen.

Erstellen von Diensten und Modulen

In diesem Schritt erstellen wir die Dienste und Module, aus denen die Anwendung besteht. Das Ziel besteht darin, eine modulare und skalierbare Architektur zu schaffen, die es verschiedenen Bereichen des Systems, wie z. B. Produkten, Kategorien, Stock, Sales und Medien, ermΓΆglicht, sich unabhΓ€ngig voneinander zu entwickeln, den Zusammenhalt aufrechtzuerhalten und die Wartung zu erleichtern. Dienste definieren Bereitstellungs- und Persistenzgrenzen; Module organisieren GeschΓ€ftsbereiche innerhalb einer modularen Dienstleistung. Bevor Sie Dateien erstellen, prΓΌfen Sie, welche Teile der DomΓ€ne eine eigene Datenbank, eine unabhΓ€ngige Freigabe, eine Integrationsvereinbarung oder einen separaten Besitz benΓΆtigen.

Schritt 1: Definieren der Dienste

ZunΓ€chst werden wir die folgenden Dienste mit jeweils klar definierten Verantwortlichkeiten erstellen:

  • Catalog (modular) – verantwortlich fΓΌr die Verwaltung von Produkten, Kategorien und Preisen;
  • Sales – verantwortlich fΓΌr die Abwicklung von Salesn und Bestellungen;
  • Aktie – verantwortlich fΓΌr die Verwaltung von BestΓ€nden und Bewegungen;
  • Security – verantwortlich fΓΌr Authentifizierung, Autorisierung und Benutzerverwaltung.

Um die Services des Beispiels zu erstellen, fΓΌhren Sie fΓΌr jeden Service einen Befehl aus. WΓ€hlen Sie im Wizard von Catalog die modulare Architektur; fΓΌr die ΓΌbrigen wΓ€hlen Sie die passende Architektur fΓΌr eine einfache Grenze.

lino service new --name Catalog
lino service new --name Sales
lino service new --name Stock
lino service new --name Security

WΓ€hrend der BefehlsausfΓΌhrung fragt die CLI nach:

  • Service-Name: zum Beispiel Catalog;
  • Anzeigename und Architekturstil: wΓ€hlen Sie eine einfache Architektur fΓΌr kompakte Grenzen oder modular, wenn der Service unabhΓ€ngige kohΓ€sive Bereiche besitzt;
  • Datenbank: wΓ€hlen Sie die Technologie, die am besten zu Ihrem Projekt passt (SQL Server, PostgreSQL usw.);

Schritt 2: Module innerhalb von Services erstellen

Nicht alle Services mΓΌssen modular sein. In unserem Projekt hat nur der Service Catalog Module, um Verantwortlichkeiten wie Merchandising und Pricing zu trennen.

FΓΌr den Service Catalog definieren wir die folgenden Module:

  • Merchandising – Verwaltung von Produkten und Kategorien;
  • Pricing – Verwaltung von Preisen, Aktionen und Γ„nderungshistorie.

Um die Module von Catalog zu erstellen, fΓΌhren Sie aus:

lino module new --service Catalog --name Merchandising
lino module new --service Catalog --name Pricing

Sie kΓΆnnen innerhalb des modularen Dienstes beliebig viele Module erstellen Catalog. DarΓΌber hinaus kΓΆnnten je nach KomplexitΓ€t einige Module in Zukunft zu eigenstΓ€ndigen Diensten werden. Die hier dargestellte Aufteilung dient lediglich didaktischen Zwecken und dient als Beispiel fΓΌr eine modulare Organisation. Verwenden Sie Module nicht nur zum Erstellen von Ordnern. Verwenden Sie sie, wenn sie einen GeschΓ€ftsbereich mit eigenen EntitΓ€ten, AnwendungsfΓ€llen, APIs, Migrationen und Ereignissen schΓΌtzen.

EndgΓΌltige Projektstruktur

Nach dem Erstellen der Dienste und Module sollte Ihre LΓΆsung eine Struktur Γ€hnlich der folgenden haben:

MyApp/
└── src/
    β”œβ”€β”€ Aspire/
    β”œβ”€β”€ Integrations/
    β”œβ”€β”€ Services/
    β”‚   β”œβ”€β”€ Catalog/
    β”‚   β”‚   β”œβ”€β”€ Modules/
    β”‚   β”‚   β”‚   β”œβ”€β”€ Merchandising/
    β”‚   β”‚   β”‚   └── Pricing/
    β”‚   β”‚   β”œβ”€β”€ MyApp.Catalog.Host
    β”‚   β”‚   └── MyApp.Catalog.Infrastructure
    β”‚   β”œβ”€β”€ Sales/
    β”‚   β”œβ”€β”€ Security/
    β”‚   β”œβ”€β”€ Shared/
    β”‚   └── Stock/
    └── WebApps/
        β”œβ”€β”€ Backoffice/
        β”‚   β”œβ”€β”€ Services/
        β”‚   β”‚   β”œβ”€β”€ Catalog/
        β”‚   β”‚   β”œβ”€β”€ Sales/
        β”‚   β”‚   β”œβ”€β”€ Security/
        β”‚   β”‚   └── Stock/
        β”‚   β”œβ”€β”€ MyApp.WebApp.Backoffice
        β”‚   └── MyApp.WebApp.Backoffice.Client
        └── Shared/
            └── MyApp.WebApp.Shared
└── tests/
    └── Services/
        β”œβ”€β”€ Catalog/
        β”‚   β”œβ”€β”€ Merchandising/
        β”‚   └── Pricing/
        β”œβ”€β”€ Sales/
        β”œβ”€β”€ Security/
        β”œβ”€β”€ Shared/
        └── Stock/

StrukturerklΓ€rung:

  • Services/: enthΓ€lt alle Systemdienste, jeder isoliert mit eigener GeschΓ€ftslogik, Infrastruktur und Hosting;
  • Modules/: Ordner innerhalb modularer Dienste, die es Ihnen ermΓΆglichen, spezifische FunktionalitΓ€ten zu organisieren und zusammenhΓ€ngenden Code zu pflegen;
  • WebApps/: Mit dem System verbundene Frontends, bereits in Dienste integriert;
  • Shared/: Bibliotheken und Ressourcen, die von Diensten und Frontends gemeinsam genutzt werden;
  • tests/: Unit- und Integrationstests, organisiert nach Dienst und Modul.

Mit dieser modularen Struktur kann jedes Team oder jeder Entwickler unabhΓ€ngig an verschiedenen Teilen des Systems arbeiten, was Skalierbarkeit, Wartung und Tests erleichtert. Nachdem Sie Dienste und Module erstellt haben, fΓΌhren Sie sie aus dotnet build Um zu bestΓ€tigen, dass Projekte korrekt an die LΓΆsung angehΓ€ngt sind, hosten Sie Aspire, freigegebene Projekte und das Test-Framework.

Authentifizierung und Autorisierung hinzufΓΌgen

Authentifizierung und Autorisierung sind wesentliche Elemente jedes modernen Systems. Durch die Authentifizierung wird nachgewiesen, wer der Benutzer ist. Die Berechtigung definiert, was dieser Benutzer ausfΓΌhren kann. In Lino CLI generiert die Authentifizierungsfunktion generiert die erforderliche Basis fΓΌr Benutzer, Rollen, Berechtigungen, Token, Zugriffsrichtlinien und die Integration mit APIs.

Schritt 1: AusfΓΌhren des Authentifizierungsbefehls

Um Authentifizierungs- und Autorisierungsfunktionen hinzuzufΓΌgen, verwenden Sie den folgenden Befehl:

lino feature auth add

CLI fΓΌhrt Sie durch die folgenden Schritte:

  • Wahl der Leistung oder des Moduls: Sie mΓΌssen angeben, wo die Authentifizierungsartefakte installiert werden. In unserem Beispielprojekt nutzen wir den Dienst Security, der die gesamte Sicherheitslogik des Systems zentralisiert;
  • ZusΓ€tzliche Einstellungen: Erstellung von Tabellen mit Benutzern, Rollen, Berechtigungen, Token und Konfiguration von Zugriffsrichtlinien;
  • Token-Lebensdauer: Definition des Ablaufs fΓΌr access token und refresh token gemÀß der Sicherheitsrichtlinie des Produkts;
  • Typ der Benutzerkennung: Auswahl des Typs, der vom Benutzermodell und den generierten VertrΓ€gen verwendet wird.

Schritt 2: Generierte Struktur

Nach AusfΓΌhrung des Befehls enthΓ€lt der Dienst Security Dateien und Ordner wie:

  • DomΓ€ne/EntitΓ€ten: Aggregate, EntitΓ€ten und Regeln fΓΌr Benutzer, Rollen, Berechtigungen und Token;
  • Infrastruktur/Persistenz: Datenbankkonfigurationen, Entity Framework-Zuordnungen und Migrationen fΓΌr Security-Tabellen;
  • Anwendung: Commands, Queries, Handlers, Authentifizierungsdienste, Token-Generierung, Anmeldeinformationsvalidierung und BerechtigungsprΓΌfungen;
  • API/Host: Endpunkte fΓΌr Anmeldung, Abmeldung, Registrierung, refresh token und geschΓΌtzte VorgΓ€nge;
  • Integration mit Web-App: UnterstΓΌtzung fΓΌr authentifizierte AblΓ€ufe, wenn eine Webanwendung vorhanden ist.

Damit verfügt Ihre Anwendung über eine robuste Authentifizierung und eine detaillierte Zugriffskontrolle, die mehrere Benutzer und unterschiedliche Berechtigungsebenen unterstützen kann. Dennoch sollte der generierte Code als solide Grundlage und nicht als abschließende Sicherheitsüberprüfung betrachtet werden. Überprüfen Sie vor der Produktion die Token-Lebensdauer, das Berechtigungsdesign, die Passwortrichtlinie, HTTPS, Geheimnisse, Ratenbegrenzung, Protokolle und Bereitstellungskonfigurationen.

Background Jobs hinzufΓΌgen

In verteilten und modularen Systemen, wie dem, mit dem wir bauen Lino CLIAllerdings kommunizieren nicht alle Dienste direkt miteinander. Um Konsistenz und ZuverlΓ€ssigkeit beim Informationsaustausch zu gewΓ€hrleisten, nutzen wir Integrationsereignisse. Um diese Ereignisse jedoch effizient und asynchron zu verarbeiten, benΓΆtigen wir Background Jobs.

Lino verwendet den Standard Outbox Pattern um sicherzustellen, dass alle von den Diensten generierten Nachrichten vor dem Versand zuverlΓ€ssig aufgezeichnet werden. Damit haben wir Folgendes erreicht:

  • Vermeiden Sie den Verlust von Ereignissen bei DienstausfΓ€llen oder Neustarts.
  • Stellen Sie sicher, dass dieselbe Nachricht nur einmal gesendet wird.
  • ErmΓΆglichen Sie die erneute Verarbeitung von Nachrichten im Falle eines Zustellungsfehlers.
  • Trennen Sie die Ereignisverarbeitung von der Hauptanwendungslogik und verbessern Sie so die Leistung und Skalierbarkeit.

Schritt 1: AusfΓΌhren des Befehls

Um Ihrem Projekt UnterstΓΌtzung fΓΌr Background Jobs hinzuzufΓΌgen, fΓΌhren Sie den folgenden Befehl aus:

lino feature background-job add

CLI fordert Sie auf, den Dienst auszuwÀhlen, in dem der Background Job installiert werden soll. Im Allgemeinen wÀhlen Sie den Dienst, der die Ereigniserzeugung zentralisiert, z. B. Catalog oder Sales. In den aktuellen Optionen kann der Assistent außerdem das Modul, die Jobbibliothek, ob Outbox-Ereignisse verarbeitet werden sollen, den Zeitplan und die Batchgrâße abfragen. Der aktuelle Vorlagenfluss verwendet Hangfire für die Ausführung wiederkehrender Jobs.

Schritt 2: Konfigurieren der AusfΓΌhrung

WΓ€hrend der Konfiguration kΓΆnnen Sie Folgendes definieren:

  • PrΓΌfintervall: Legt fest, wie oft der Background Job die Tabelle ΓΌberprΓΌft Outbox fΓΌr neue Nachrichten. Ein zu kurzes Intervall kann die Ressourcennutzung erhΓΆhen, wΓ€hrend ein zu langes Intervall die Ereigniszustellung verzΓΆgern kann.
  • Stapel von gleichzeitig verarbeiteten DatensΓ€tzen: steuert, wie viele Ereignisse pro Lauf gelesen und gesendet werden. Grâßere Stapel kΓΆnnen die Leistung steigern, erfordern jedoch mehr Speicher und Verarbeitung;
  • Abrufrichtlinie: Falls das Senden von Nachrichten fehlschlΓ€gt, kΓΆnnen Sie konfigurieren, wie oft der Job versucht, erneut zu senden.

Diese Parameter hÀngen von der Grâße Ihres Systems, der MaschinenkapazitÀt und dem erwarteten Ereignisaufkommen ab.

Schritt 3: Generierte Struktur

Nach der Konfiguration verfΓΌgt das Projekt ΓΌber einen Background Job, der Nachrichten aus den Tabellen verarbeiten kann Outbox in jedem Dienst.

  1. Der Anwendungsfall Γ€ndert die DomΓ€ne und zeichnet ein DomΓ€nen- oder Integrationsereignis auf.
  2. Die Arbeitseinheit speichert die GeschΓ€ftsdaten und Nachrichten von Outbox in derselben Transaktion.
  3. Hangfire fΓΌhrt wiederkehrende Jobs aus, die ausstehende Nachrichten stapelweise lesen.
  4. Nachrichten werden an die konfigurierte Integrations-Engine wie RabbitMQ verΓΆffentlicht, wenn die asynchrone Kommunikation aktiviert ist.
  5. Abgeschlossene, fehlgeschlagene, alte oder hΓ€ngengebliebene Nachrichten kΓΆnnen von der fΓΌr den Job generierten Logik und Konfiguration verarbeitet werden.

Dadurch wird sichergestellt, dass alle Integrationsereignisse zuverlΓ€ssig und effizient verarbeitet werden, sodass mehrere Dienste und Module asynchron kommunizieren kΓΆnnen, ohne die Leistung des Hauptsystems zu beeintrΓ€chtigen. Die wichtigste Betriebsregel besteht darin, die Transaktionsgrenze klar zu halten: Ereignisse, die ΓΌber Outbox gesendet werden mΓΌssen, mΓΌssen im selben Transaktionsfluss erstellt werden wie die GeschΓ€ftsΓ€nderung, die sie darstellen.

EntitΓ€ten und AufzΓ€hlungen erstellen

In diesem Abschnitt gehen wir detailliert auf den Entwurf der EntitΓ€ten, AufzΓ€hlungen und Value Objects der Anwendung ein und zeigen, in welchen Diensten und Modulen jedes Element erstellt wird.

1. Erstellen der EntitΓ€t Category

Um die EntitΓ€t Category im Service Catalog und im Modul Merchandising zu erstellen, fΓΌhren Sie aus:

lino entity new --service Catalog --module Merchandising --name Category

Die EntitΓ€t wird im Dienst erstellt Catalog und im Modul Merchandising mit folgendem Aufbau:

β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PK β”‚ FK β”‚ Property name β”‚ Type   β”‚ Length β”‚ Required β”‚ Auto-increment β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ x  β”‚    β”‚ Id            β”‚ Guid   β”‚        β”‚    x     β”‚       x        β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Name          β”‚ string β”‚   50   β”‚    x     β”‚                β”‚
β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Erstellen der EntitΓ€t Product

Anschließend erstellen wir die EntitÀt Product im selben Service und Modul. In diesem Ablauf werden das Value Object ProductDimension und die Enum ProductStatus direkt im Wizard zur Erstellung der EntitÀt als Teil des Aggregats Product konfiguriert:

lino entity new --service Catalog --module Merchandising --name Product

FΓΌgen Sie wΓ€hrend der AusfΓΌhrung die einfachen Eigenschaften, die Beziehung zu Category, die Eigenschaft Dimensions vom Typ Value Object und die Eigenschaft Status vom Typ Enum hinzu.

β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PK β”‚ FK β”‚ Property name β”‚ Type        β”‚ Length β”‚ Required β”‚ Auto-increment β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ x  β”‚    β”‚ Id            β”‚ Guid        β”‚        β”‚    x     β”‚       x        β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Name          β”‚ string      β”‚  100   β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Description   β”‚ string      β”‚  500   β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Price         β”‚ decimal     β”‚        β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚ x  β”‚ CategoryId    β”‚ Category    β”‚        β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Dimensions    β”‚ ValueObject β”‚        β”‚          β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Status        β”‚ Enum        β”‚        β”‚    x     β”‚                β”‚
β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2.1 Konfigurieren des Value Object ProductDimension innerhalb von Product

Im Szenario dieses Leitfadens wird ProductDimension nicht durch einen separaten Befehl erstellt. Es wird wΓ€hrend lino entity new fΓΌr Product als Eigenschaft Dimensions hinzugefΓΌgt und stellt die Produktabmessungen dar:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Property name β”‚ Type    β”‚ Length β”‚ Required β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Width         β”‚ decimal β”‚        β”‚    x     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Height        β”‚ decimal β”‚        β”‚    x     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Depth         β”‚ decimal β”‚        β”‚    x     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Hinweis: Der Befehl lino value-object new existiert fΓΌr Szenarien, in denen das Value Object separat erstellt werden muss. Verwenden Sie in diesen FΓ€llen die Argumente fΓΌr Ziel-Service und Ziel-Modul:

lino value-object new --service <ServiceName> --module <ModuleName> --name <ValueObjectName>

2.2 Konfigurieren der Enum ProductStatus innerhalb von Product

Ebenso wird ProductStatus wΓ€hrend lino entity new fΓΌr Product als Eigenschaft Status konfiguriert. Sie definiert den Status des Produkts:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Value β”‚ Name         β”‚ Display Name β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 1     β”‚ Active       β”‚ Active       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 2     β”‚ Inactive     β”‚ Inactive     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 3     β”‚ Discontinued β”‚ Discontinued β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Hinweis: Der Befehl lino enumeration new kann ebenfalls verwendet werden, wenn eine enum in einem anderen Szenario separat erstellt werden muss:

lino enumeration new --service <ServiceName> --module <ModuleName> --name <EnumerationName>

3. HinzufΓΌgen neuer Eigenschaften

WΓ€hrend sich das Projekt weiterentwickelt, kΓΆnnen wir vorhandene EntitΓ€ten bearbeiten, um neue Eigenschaften hinzuzufΓΌgen. Beispielsweise fΓΌgen wir der EntitΓ€t eine Liste mit Bildern hinzu Product:

lino entity edit --service Catalog --module Merchandising --entity Product

In demselben Ablauf erstellen wir die Eigenschaft Images vom Typ List<ProductImage>. Da ProductImage zum Aggregat Product gehΓΆrt, wird seine Struktur ebenfalls wΓ€hrend lino entity edit fΓΌr Product konfiguriert:

β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PK β”‚ FK β”‚ Property name β”‚ Type               β”‚ Length β”‚ Required β”‚ Auto-increment β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ x  β”‚    β”‚ Id            β”‚ Guid               β”‚        β”‚    x     β”‚       x        β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Name          β”‚ string             β”‚  100   β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Description   β”‚ string             β”‚  500   β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Price         β”‚ decimal            β”‚        β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚ x  β”‚ CategoryId    β”‚ EntityId           β”‚        β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Dimensions    β”‚ ValueObject        β”‚        β”‚          β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Status        β”‚ Enum               β”‚        β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚ x  β”‚ Images        β”‚ List β”‚        β”‚          β”‚                β”‚
β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3.1 Konfigurieren von ProductImage innerhalb von Product

ProductImage wird in diesem Szenario nicht durch einen separaten Befehl erstellt. Es wird wΓ€hrend der Bearbeitung von Product als Element der Collection Images konfiguriert und hat die folgende Struktur:

β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PK β”‚ FK β”‚ Property name β”‚ Type           β”‚ Length β”‚ Required β”‚ Auto-increment β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ x  β”‚    β”‚ Id            β”‚ Guid           β”‚        β”‚    x     β”‚       x        β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚ x  β”‚ ProductId     β”‚ EntityId       β”‚        β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ UploadDate    β”‚ DateTimeOffset β”‚        β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Image         β”‚ File           β”‚        β”‚    x     β”‚                β”‚
β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Hinweis: Der Befehl lino entity new existiert, um unabhΓ€ngige EntitΓ€ten in anderen Szenarien zu erstellen. Wenn die EntitΓ€t nicht Teil der Bearbeitung eines bestehenden Aggregats ist, verwenden Sie:

lino entity new --service <ServiceName> --module <ModuleName> --name <EntityName>

4. EntitΓ€ten fΓΌr andere Dienste erstellen

Im Dienst Sales, wir erstellen die EntitΓ€t ProductSnapshot, die durch Integrationsveranstaltungen gespeist wird. Als ursprΓΌngliche ID der EntitΓ€t Product kommt aus dem Dienst Catalog, es kann hier nicht automatisch inkrementell sein.

lino entity new --service Sales --name ProductSnapshot
β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PK β”‚ FK β”‚ Property name β”‚ Type    β”‚ Length β”‚ Required β”‚ Auto-increment β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ x  β”‚    β”‚ Id            β”‚ Guid    β”‚        β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Name          β”‚ string  β”‚  100   β”‚    x     β”‚                β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Price         β”‚ decimal β”‚        β”‚    x     β”‚                β”‚
β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Hinweis: Nur die wesentlichen Felder wurden in ProductSnapshot fΓΌr den Service Sales repliziert. ErgΓ€nzende EntitΓ€ten wie Customer, Order und StockItem werden hier nicht detailliert beschrieben, um die Dokumentation zu vereinfachen. ProductSnapshot funktioniert als shadow entity: eine lokale, minimale und kontrollierte Kopie von Daten, deren Besitzer in einem anderen Service liegt. Dadurch kann Sales die erforderlichen Produktdaten abfragen, ohne direkt von der EntitΓ€t oder Datenbank von Catalog abhΓ€ngig zu sein.

Diese Art von Struktur kΓΆnnte auch mit dem Befehl lino shadow new erstellt werden, einem Alias von lino shadow-entity new. In diesem Ablauf kopiert Lino die Struktur einer EntitΓ€t aus einem anderen Service oder Modul und ermΓΆglicht die Auswahl nur der Eigenschaften, die fΓΌr den konsumierenden Kontext sinnvoll sind.

lino shadow new --service <ServiceName> --module <ModuleName> --name <ShadowEntityName>

Im Beispiel ist die QuellentitΓ€t Catalog.Merchandising.Product und das Ziel der Service Sales, wobei nur die fΓΌr Sales benΓΆtigten Felder beibehalten werden.

Erstellen von Ereignissen und ihren Handlers

Um es noch einmal zusammenzufassen: Im vorherigen Thema haben wir einen modularen Dienst erstellt Catalog.Merchandising die EntitΓ€ten Product, Category Und ProductImage, wΓ€hrend des Dienstes Sales Wir erschaffen die Einheit ProductSnapshot.

Lassen Sie uns nun DomΓ€nenereignisse und Integrationsereignisse erstellen. Das Ziel besteht darin, Produkte fΓΌr den Dienst zu erstellen oder zu aktualisieren Catalog, werden diese Γ„nderungen auf Verbraucherdienste repliziert, z Sales Und Aktie.

1. DomΓ€nenereignisse erstellen

Der erste Schritt besteht darin, DomΓ€nenereignisse zu erstellen ProductCreated und ProductUpdated mit dem Befehl:

lino event new

WΓ€hrend der Erstellung kΓΆnnen wir das Ereignis einem Handlers zuordnen und gleichzeitig das AuslΓΆsen eines Integrationsereignisses konfigurieren. Dadurch wird die Erstellung aller notwendigen AblΓ€ufe zentralisiert.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Question                                             β”‚ Answer                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a service:                                    β”‚ Catalog                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a module:                                     β”‚ Merchandising                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a entity:                                     β”‚ Product                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event type:                               β”‚ Domain Event                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Enter the name of the event:                         β”‚ ProductCreated                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Do you want to create an associated event handler?   β”‚ Yes                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Trigger a integration event?                         β”‚ Yes                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Choose the integration event to be triggered:        β”‚ (Create new integration event) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Enter the name of the event:                         β”‚ ProductCreated                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Which model will be used for this integration event? β”‚ Creation model                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Auf die gleiche Weise gestalten wir das Event ProductUpdated:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Question                                             β”‚ Answer                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a service:                                    β”‚ Catalog                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a module:                                     β”‚ Merchandising                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a entity:                                     β”‚ Product                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event type:                               β”‚ Domain Event                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Enter the name of the event:                         β”‚ ProductUpdated                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Do you want to create an associated event handler?   β”‚ Yes                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Trigger a integration event?                         β”‚ Yes                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Choose the integration event to be triggered:        β”‚ (Create new integration event) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Enter the name of the event:                         β”‚ ProductUpdated                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Which model will be used for this integration event? β”‚ Update model                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Damit haben wir:

2. Integrationsereignishandler erstellen

Der nΓ€chste Schritt besteht darin, zu definieren, welche Dienste die Integrationsereignisse nutzen. Dazu verwenden wir:

lino event-handler new

Der Erstellungsablauf umfasst:

Zum Beispiel im Dienst Sales haben wir die Handlers dafΓΌr erstellt ProductCreated und ProductUpdated Dadurch werden die ausgelΓΆsten Ereignisse verarbeitet Catalog.Merchandising.Produkt:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Question                                   β”‚ Answer            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a service:                          β”‚ Sales             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a entity:                           β”‚ ProductSnapshot   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event type:                     β”‚ Integration Event β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event's service to be consumed: β”‚ Catalog           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event's module to be consumed:  β”‚ Merchandising     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event's entity to be consumed:  β”‚ Product           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Choose the event to be consumed:           β”‚ ProductCreated    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Enter the name of the event handler:       β”‚ ProductCreated    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Question                                   β”‚ Answer            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a service:                          β”‚ Sales             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a entity:                           β”‚ ProductSnapshot   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event type:                     β”‚ Integration Event β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event's service to be consumed: β”‚ Catalog           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event's module to be consumed:  β”‚ Merchandising     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select the event's entity to be consumed:  β”‚ Product           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Choose the event to be consumed:           β”‚ ProductUpdated    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Enter the name of the event handler:       β”‚ ProductUpdated    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Damit haben wir zwei Integrationsereignishandler im Dienst Sales, wobei nur die erforderlichen Felder aus den Integrationsereignissen des verwendet werden Catalog.Merchandising. Dadurch wird sichergestellt, dass replizierte Tabellen nur wesentliche Daten behalten, wodurch Speicher und Leistung optimiert werden. In Bezug auf die Architektur sieht der erwartete Ablauf wie folgt aus: Der Befehlshandler Γ€ndert das Aggregat, das DomΓ€nenereignis wird ausgelΓΆst, die Handlers bereiten das Integrationsereignis vor, Outbox speichert die Nachricht, der Background Job verarbeitet das Problem und die Messaging-Engine ΓΌbermittelt die Nachricht an Verbraucher. Dies vermeidet eine synchrone Kopplung zwischen Diensten und verringert das Risiko, dass die Datenbank geΓ€ndert wird, ohne dass das entsprechende Ereignis verΓΆffentlicht wird.

Generieren von Webseiten, APIs, Commandsn und Queries

Einer der großen Vorteile von Lino CLI besteht darin, die integrierte Erstellung von Webseiten, APIs, Commandsn und Queries auf automatisierte Weise zu ermâglichen und so den gesamten Entwicklungsablauf zu vereinfachen. Wenn das DomÀnenmodell stabil genug ist, erstellt dieser Befehl einen vollstÀndigen Pfad vom Bildschirm zur Persistenz, wodurch die in den vorherigen Schritten durchgeführte Modellierungsarbeit für den Endbenutzer sichtbar wird. Führen Sie zum Starten einfach den folgenden Befehl aus:

lino page new

WΓ€hrend des Prozesses werden Sie:

Mit diesem Befehl erhalten Sie eine funktionsfÀhige Anwendung, ohne die Schnittstellenschicht, APIs und GeschÀftslogik manuell schreiben zu müssen, wodurch der Standard und die Konsistenz zwischen den Diensten gewahrt bleiben. Überprüfen Sie dennoch die GeschÀftsregeln und Validierungen nach der Generierung, da nicht jede Regel allein aus Eigenschaftsmetadaten abgeleitet werden kann.

FΓΌr dieses Projekt kΓΆnnen wir integrierte Seiten fΓΌr die folgenden EntitΓ€ten generieren:

Nach der Generierung der Seiten, APIs und Commands/Queries ist die Anwendung bereit, vollstΓ€ndig zwischen Frontend und Backend zu interagieren, wobei Validierungen, Routen und Persistenz bereits automatisch von der konfiguriert werden Lino CLI. Laufen dotnet build nach der Generierung, um fehlerhafte Referenzen, inkonsistente VertrΓ€ge oder Auswirkungen kΓΌrzlicher ModellΓ€nderungen frΓΌhzeitig zu erkennen.

Migrationen erstellen und anwenden

Generieren Sie nach dem Erstellen oder Γ„ndern von EntitΓ€ten, Value Objects, AufzΓ€hlungen, Beziehungen, Authentifizierung, Tenant-UnterstΓΌtzung oder der Persistenz von Background Jobs Migrationen, um Datenbank und Code aufeinander abzustimmen. Durch die Migration wird die ModellΓ€nderung in ein explizites, versionierbares und ΓΌberprΓΌfbares Artefakt umgewandelt.

Die Lino CLI koordiniert diesen Prozess mit Entity Framework, wΓ€hlt den richtigen Dienst/Modul aus, verwendet die aktuelle Version des Dienstes und organisiert die generierten Skripte, um die RΓΌckverfolgbarkeit zu erleichtern.

Schritt 1: Erstellen einer Migration

Um eine neue Migration zu erstellen, fΓΌhren Sie Folgendes aus:

lino database migrations add

Der Befehl kann auch Aliase wie lino database migrations new Und lino database migrations create, akzeptieren; der bevorzugte Weg in der Dokumentation ist jedoch add.

Bei der AusfΓΌhrung mΓΌssen Sie Folgendes mitteilen:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Question                                  β”‚ Answer            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a service:                         β”‚ Catalog           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Select a module:                          β”‚ Merchandising     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Current version of the service:           β”‚ 0.1.0             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Provide a description for this migration: β”‚ Initial migration β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Wenn Sie den Dienst und das Modul bereits kennen, kΓΆnnen Sie diese Daten direkt eingeben:

lino database migrations add --service <ServiceName> --module <ModuleName>

Schritt 2: Was wird generiert?

Beim BestΓ€tigen der Erstellung bereitet Lino die richtigen Entity Framework-Commands fΓΌr das ausgewΓ€hlte Dienst- oder Modulpersistenzprojekt vor. Bei einem modularen Dienst bleibt die Migration im entsprechenden Modul isoliert, wodurch eine Vermischung von Γ„nderungen aus verschiedenen Kontexten vermieden wird.

Schritt 3: Migrationen auflisten und anwenden

Bevor Sie Γ„nderungen an einer Datenbank anwenden, listen Sie die bekannten Migrationen auf und bestΓ€tigen Sie, dass die erwartete Migration vorhanden ist:

lino database migrations list --service <ServiceName> --module <ModuleName>

So wenden Sie Migrationen auf die konfigurierte Umgebung an:

lino database migrations apply --service <ServiceName> --module <ModuleName>

In der lokalen Entwicklung beschleunigt dieser Ablauf die Modellvalidierung. FΓΌhren Sie in gemeinsam genutzten oder Produktionsumgebungen Migrationen ΓΌber den vom Team definierten Bereitstellungsprozess durch, mit SkriptΓΌberprΓΌfung, Genehmigung und Sicherung bei Bedarf.

Schritt 4: Umkehren oder Entfernen in einer kontrollierten Umgebung

Verwenden revert Wenn Sie eine in einer kontrollierten Umgebung angewendete Migration zurΓΌckgeben mΓΌssen, beachten Sie, dass der Vorgang abhΓ€ngig vom Inhalt der Migration destruktive Commands ausfΓΌhren kann:

lino database migrations revert --service <ServiceName> --module <ModuleName>

Verwenden remove So verwerfen Sie die letzte nicht festgeschriebene Migration, normalerweise bevor Sie die Γ„nderung festschreiben oder verΓΆffentlichen:

lino database migrations remove --service <ServiceName> --module <ModuleName>

Gute Praktiken

Durch Befolgen dieses Ablaufs bleibt die Datenbank mit dem in Lino definierten DomΓ€nenmodell konsistent und jede SchemaΓ€nderung ist dokumentiert, nachvollziehbar und kann vor der Bereitstellung ΓΌberprΓΌft werden.

Schritt 5: Anwendung lokal validieren

Wenn Projekt, Web App, Services, Module, EntitΓ€ten, Migrations, APIs, Commands und Queries bereit sind, validieren Sie die Anwendung, bevor Sie Docker-Images erzeugen. Kompilieren Sie zuerst die Solution, um zu bestΓ€tigen, dass alle generierten Projekte, Contracts und Clients weiterhin konsistent sind:

dotnet build

Führen Sie anschließend die Anwendung über den Aspire AppHost aus:

dotnet run --project src/Aspire/AppHost/<ProjectName>.AppHost.csproj

Verwenden Sie das Aspire-Dashboard, um zu prΓΌfen, ob APIs, Web App, Datenbank, Cache, Messaging und Background Jobs korrekt gestartet wurden. Testen Sie danach die wichtigsten AblΓ€ufe im Backoffice: generierte Seiten, Blazor-Aufrufe an die Api.Client-Projekte, angewendete Migrations, Authentifizierung, wenn aktiviert, sowie Events oder Jobs, wenn sie Teil des Szenarios sind.

Wenn die Anwendung kompiliert, lokal ausgefΓΌhrt wird und die wichtigsten AblΓ€ufe validiert sind, ist das Projekt bereit fΓΌr den Packaging-Schritt.

Generieren von Docker-Images

Nachdem die Anwendung kompiliert, lokal ΓΌber den AppHost ausgefΓΌhrt wird und die wichtigsten AblΓ€ufe getestet wurden, kΓΆnnen Sie Docker-Images der Services und Webanwendungen erzeugen, um sie spΓ€ter in einem Container-Registry zu verΓΆffentlichen. Verwenden Sie lino build, wenn die ausgewΓ€hlten Elemente bereit sind, als Images gepackt zu werden.

Die Lino CLI vereinfacht diesen Vorgang mit dem Befehl:

lino build

Bei der AusfΓΌhrung sehen Sie eine Liste aller im Projekt verfΓΌgbaren Dienste und Webanwendungen sowie deren aktuelle Versionen:

Select the services or web applications you want to include in the build:

> [ ] Services
    [ ] Catalog |0.1.0|
    [ ] Sales |0.1.0|
    [ ] Security |0.1.0|
    [ ] Stock |0.1.0|
  [ ] Web applications
    [ ] Backoffice |0.1.0|

Sie kΓΆnnen einen oder mehrere Dienste und Webanwendungen auswΓ€hlen, um gleichzeitig Bilder zu generieren. Markieren Sie einfach die gewΓΌnschten Artikel.

Anschließend werden Sie aufgefordert, auszuwÀhlen, wie Sie die Version der generierten Bilder aktualisieren mâchten. Die verfügbaren Optionen sind:

Nach der Auswahl der Dienste und der Definition des Versionsinkrements wird die Lino CLI fΓΌhrt aus:

Wenn am Ende des Prozesses alle Webdienste und Anwendungen ausgewΓ€hlt wurden, haben die generierten Bilder die folgende Struktur:

Im Allgemeinen generieren einfache Dienste in der Regel Repositorys wie project-name/services/service-name-api:1.2.3, Modulare Dienste verwenden Hosts als project-name/services/service-name-host:1.2.3, und Blazor-Anwendungen verwenden Pfade wie project-name/webapps/webapp-name:1.2.3.

Beobachtung: Dieser Prozess gewΓ€hrleistet die Konsistenz zwischen dem Code und der Version der Docker-Images, erleichtert die Bereitstellung und Wartung mehrerer Umgebungen und ermΓΆglicht darΓΌber hinaus die Isolierung jedes Dienstes in unabhΓ€ngigen Containern. Nachdem das lokale Image generiert wurde, verΓΆffentlichen Sie es in der von Ihrer Bereitstellungsplattform verwendeten Registrierung, z. B. Docker Hub, GitHub Container Registry, AWS ECR, Azure Container Registry oder einer anderen OCI-kompatiblen Registrierung. FΓΌgen Sie keine Geheimnisse, Produktionsverbindungszeichenfolgen oder Anmeldeinformationen in das Image ein.

Erstellen von Versionen in der Anwendung

Lino verwaltet die Betriebsversion jedes Dienstes in src/Services/<ServiceName>/version.txt und jede Webanwendung in src/WebApps/<WebAppName>/version.txt. Dadurch kΓΆnnen Sie unabhΓ€ngige Releases fΓΌr jedes bereitstellbare Element planen.

Überprüfen Sie vor einem Versionswechsel den aktuellen Stand:

lino version list

Verwenden lino version show wenn Sie einen bestimmten Dienst oder eine bestimmte Webanwendung konsultieren mΓΌssen.

Das Erstellen neuer Versionen von Webdiensten oder Anwendungen ist mit Lino CLI ein einfacher, zentralisierter Prozess. FΓΌhren Sie einfach den Befehl aus:

lino version bump

Genau wie beim Generieren von Docker-Images wird Ihnen beim AusfΓΌhren dieses Befehls eine vollstΓ€ndige Liste aller Dienste und Webanwendungen in Ihrem Projekt angezeigt. Nur die Version der von Ihnen ausgewΓ€hlten Elemente wird erhΓΆht, wΓ€hrend der Rest unverΓ€ndert bleibt.

Select the services or web applications that will have version changes:

> [ ] Services
    [ ] Catalog |0.1.0|
    [ ] Sales |0.1.0|
    [ ] Security |0.1.0|
    [ ] Stock |0.1.0|
  [ ] Web applications
    [ ] Backoffice |0.1.0|

Nachdem Sie die gewΓΌnschten Elemente ausgewΓ€hlt haben, werden Sie aufgefordert, die Art der VersionserhΓΆhung auszuwΓ€hlen. Die verfΓΌgbaren Optionen sind:

Es ist wichtig hervorzuheben, dass die Versionen von Webdiensten und Anwendungen einen direkten Einfluss haben auf:

Bevor Sie eine ErhΓΆhung anwenden, ΓΌberprΓΌfen Sie CodeΓ€nderungen, Migrationen, Integrationsereignisse, API-VertrΓ€ge und Frontend-Γ„nderungen, die Teil der Version sind. Eine Version Patch mΓΌssen kompatible Fixes darstellen, Unerheblich mΓΌssen kompatible ErgΓ€nzungen darstellen, und Wesentlich Es sollte Γ„nderungen vorbehalten bleiben, die eine Anpassung der Verbraucher erfordern.

Damit schließen wir die Schritt-für-Schritt-Anleitung zu allen wesentlichen Commandsn zum Erstellen eines Webprojekts mit ab Lino CLI, von der Installation über die Erstellung von Diensten, EntitÀten, Ereignissen und Seiten bis hin zur Docker-Image-Generierung und Versionierung. Der gesamte Ablauf ist nachvollziehbar: DomÀne modellieren, AnwendungsfÀlle und Bildschirme generieren, mit Builds und Tests validieren, Migrationen erstellen, Bilder mit Versions-Tags verâffentlichen und jeden Dienst oder jede Webanwendung mit einem expliziten SemVer-Wert freigeben.

Vergessen Sie nicht, unserem Kanal zu folgen YouTube um detaillierte Tutorials, praktische Demonstrationen und Tipps zur Verwendung des Tools zu verfolgen, von einfachen VorgΓ€ngen bis hin zu erweiterten Funktionen.

Ein unbehandelter Fehler ist aufgetreten. Aktualisieren πŸ—™