Verwalten von Updates der Abhängigkeiten im .NET-Paket

Abgeschlossen

Früher oder später werden Sie eine Bibliothek aktualisieren müssen. Möglicherweise wurde eine Funktion als veraltet markiert, oder es gibt ein neues Feature in einer höheren Version eines von Ihnen verwendeten Pakets.

Bevor Sie versuchen, eine Bibliothek zu aktualisieren, sollten Sie folgende Aspekte berücksichtigen:

  • Updatetyp: Welche Art von Update ist verfügbar? Handelt es sich um eine kleine Fehlerbehebung? Fügt das Update ein neues Feature hinzu, das Sie benötigen? Wird Ihr Code unterbrochen? Sie können die Art des Updates mithilfe eines Systems namens semantische Versionsverwaltung kommunizieren. Die Art, auf die die Versionsnummer der Bibliothek ausgedrückt wird, gibt für Entwickler*innen an, um welche Art von Update es sich handelt.
  • Herausfinden, ob das Projekt richtig konfiguriert ist: Sie können Ihr .NET-Projekt so konfigurieren, dass nur die von Ihnen gewünschten Updatetypen abgerufen werden. Damit erfolgt nur dann eine Aktualisierung, wenn eine spezifische Art von Update verfügbar ist. Diese Vorgehensweise wird empfohlen, da Sie vor unerwünschten Überraschungen geschützt werden.
  • Sicherheitsprobleme: Zur Verwaltung von Projektabhängigkeiten im Laufe der Zeit gehört auch, dass mögliche Probleme berücksichtigt werden. Probleme können beispielsweise dann auftreten, wenn Sicherheitsrisiken entdeckt werden. Im Idealfall werden Patches veröffentlicht, die Sie herunterladen können. Das .NET Core-Tool unterstützt Sie bei der Ausführung eines Audits Ihrer Bibliotheken, um zu ermitteln, ob es Pakete gibt, die aktualisiert werden sollten. Außerdem können Sie die entsprechenden Maßnahmen ergreifen, um ein Problem zu beheben.

Verwenden der semantischen Versionierung

Es gibt einen Industriestandard namens semantische Versionierung, mit dem Sie die Art der Änderung ausdrücken, die Sie oder andere Entwickler*innen an einer Bibliothek vornehmen. Die semantische Versionsverwaltung stellt sicher, dass ein Paket über eine Versionsnummer verfügt und dass diese in die folgenden Abschnitte unterteilt ist:

  • Hauptversion: Hierbei handelt es sich um die Zahl ganz links. Bei der Versionsnummer „1.0.0“ beispielsweise ist dies die Zahl 1. Eine Änderung an dieser Zahl bedeutet, dass Sie Breaking Changes im Code erwarten können. Möglicherweise müssen Sie einen Teil Ihres Codes neu schreiben.
  • Nebenversion: Hierbei handelt es sich um die Zahl in der Mitte. Bei der Versionsnummer „1.2.0“ beispielsweise ist dies die Zahl 2. Eine Änderung an dieser Zahl bedeutet, dass Features hinzugefügt wurden. Ihr Code sollte weiterhin funktionieren. In der Regel ist es sicher, das Update zu akzeptieren.
  • Patchversion: Hierbei handelt es sich um die Zahl ganz rechts. Bei der Versionsnummer „1.2.3“ beispielsweise ist dies die Zahl 3. Eine Änderung an dieser Zahl bedeutet, dass eine Änderung angewendet wurde, mit der etwas im Code behoben wurde, das hätte funktionieren sollen. Es sollte sicher sein, das Update zu akzeptieren.

In der folgenden Tabelle wird veranschaulicht, wie die Versionsnummer sich für jeden Versionstyp ändert:

Typ Änderung
Hauptversion Die Version 1.0.0 wird in 2.0.0 geändert.
Nebenversion Die Version 1.1.1 wird in 1.2.0 geändert.
Patchversion Die Version 1.0.1 wird in 1.0.2 geändert.

Viele Unternehmen und Entwickler verwenden dieses System. Wenn Sie Pakete veröffentlichen und in die NuGet-Registrierung pushen möchten, sollten Sie die semantische Versionsverwaltung verwenden. Dies wird erwartet. Selbst wenn Sie nur Pakete aus der NuGet-Registrierung herunterladen, können Sie davon ausgehen, dass diese Pakete die semantische Versionsverwaltung nutzen.

Änderungen an einem Paket bergen Risiken – beispielsweise das Risiko, dass ein Fehler Schaden in Ihrem Unternehmen anrichten kann. Einige dieser Risiken können dazu führen, dass Sie einen Teil des Codes neu schreiben müssen. Das Umschreiben von Code kostet Zeit und Geld.

Vorgehensweise für Updates

Als .NET-Entwickler*in können Sie .NET das gewünschte Updateverhalten mitteilen. Berücksichtigen Sie bei Updates die Risiken. Im Folgenden werden einige Ansätze erläutert:

  • Hauptversion: Ich möchte Updates auf die neueste Hauptversion durchführen, sobald diese verfügbar ist. Ich akzeptiere die Tatsache, dass ich möglicherweise meinen Code ändern muss.
  • Nebenversion: Es ist akzeptabel, dass ein neues Feature hinzugefügt wird. Ich möchte keine Breaking Changes für meinen Code.
  • Patchversion: Nur Fehlerbehebungen sind akzeptabel.

Wenn Sie ein neues oder kleineres .NET-Projekt verwalten, können Sie die Updatestrategie locker definieren. Beispielsweise können Sie Ihr Projekt immer auf die neueste Version aktualisieren. Bei komplexeren Projekten sind einige Nuancen zu beachten, aber darauf kommen wir in einem anderen Modul zurück.

Im Allgemeinen gilt: je kleine die Abhängigkeit ist, die Sie aktualisieren, desto weniger Abhängigkeiten weist diese auf und umso wahrscheinlicher ist es, dass der Updateprozess einfach ist.

Konfigurieren der Projektdatei für Updates

Wenn Sie eine oder mehrere Abhängigkeiten hinzufügen, sollten Sie die Projektdatei entsprechend konfigurieren, um ein vorhersagbares Verhalten beim Wiederherstellen, Kompilieren oder Ausführen Ihres Projekts zu erzielen. Sie können den Ansatz angeben, den Sie für ein Paket verwenden möchten. NuGet verwendet die Konzepte „Versionsbereiche“ und „fließende Versionen“.

Zunächst werden Versionsbereiche erläutert. Diese Notation wird zum Angeben bestimmter Versionsbereiche verwendet, die aufgelöst werden sollen.

Notation Angewendete Regel BESCHREIBUNG
1.0 x >= 1.0 Mindestversion, einschließlich
(1.0,) x > 1.0 Mindestversion, ausschließlich
[1.0] x == 1.0 Exakte Versionsübereinstimmung
(,1.0] x ≤ 1.0 Maximalversion, einschließlich
(,1.0) x < 1.0 Maximalversion, ausschließlich
[1.0,2.0] 1.0 ≤ x ≤ 2.0 Exakter Bereich, einschließlich
(1.0,2.0) 1.0 < x < 2.0 Exakter Bereich, ausschließlich
[1.0,2.0) 1.0 ≤ x < 2.0 Kombination aus Minimalversion (einschließlich) und Maximalversion (ausschließlich)
(1.0) ungültig ungültig

NuGet unterstützt auch eine Notation für fließende Versionen für das Suffix der Versionsnummer einer Haupt-, Neben-, Patch- oder Vorabversion. Diese Notation ist ein Sternchen (*). Beispielsweise bedeutet die Versionsangabe 6.0.* „Verwenden Sie die neueste Version 6.0.x“. In einem anderen Beispiel bedeutet 4.*‚ „die neueste 4.x-Version verwenden“. Die Verwendung einer gleitenden Version reduziert Änderungen an der Projektdatei und behält zugleich mit der neuesten Version einer Abhängigkeit den neuesten Stand bei.

Hinweis

Es wird jedoch empfohlen, eine bestimmte Version zu installieren, anstatt fließende Notationen zu verwenden. Durch Installieren einer bestimmten Version wird sichergestellt, dass Ihre Builds wiederholbar sind, sofern Sie nicht explizit ein Update einer Abhängigkeit anfordern.

Wenn Sie eine fließende Version verwenden, löst NuGet die neueste Version eines Pakets auf, die dem Versionsmuster entspricht. Im folgenden Beispiel wird mit „6.0.*“ die neueste Version eines Pakets abgerufen, das mit „6.0“ beginnt. Das ist Version 6.0.1.

Diagram showing choosing the latest version when a floating version is requested.

Im Folgenden finden Sie Beispiele für die Konfiguration von Haupt-, Neben- oder Patchversionen:

<!-- Accepts any version 6.1 and later. -->
<PackageReference Include="ExamplePackage" Version="6.1" />

<!-- Accepts any 6.x.y version. -->
<PackageReference Include="ExamplePackage" Version="6.*" />
<PackageReference Include="ExamplePackage" Version="[6,7)" />

<!-- Accepts any later version, but not including 4.1.3. Could be
     used to guarantee a dependency with a specific bug fix. -->
<PackageReference Include="ExamplePackage" Version="(4.1.3,)" />

<!-- Accepts any version earlier than 5.x, which might be used to prevent pulling in a later
     version of a dependency that changed its interface. However, we don't recommend this form because determining the earliest version can be difficult. -->
<PackageReference Include="ExamplePackage" Version="(,5.0)" />

<!-- Accepts any 1.x or 2.x version, but not 0.x or 3.x and later. -->
<PackageReference Include="ExamplePackage" Version="[1,3)" />

<!-- Accepts 1.3.2 up to 1.4.x, but not 1.5 and later. -->
<PackageReference Include="ExamplePackage" Version="[1.3.2,1.5)" />

Suchen und Aktualisieren veralteter Pakete

Der Befehl dotnet list package --outdated listet veraltete Pakete auf. Mit diesem Befehl erfahren Sie, ob neuere Versionen von Paketen verfügbar sind. Unten sehen Sie eine typische Ausgabe dieses Befehls:

Top-level Package      Requested   Resolved   Latest
> Humanizer            2.7.*       2.7.9      2.8.26

Hier finden Sie die Bedeutungen der Namen der Spalten in der Ausgabe:

  • Requested: Die Version oder der Versionsbereich, die bzw. den Sie angegeben haben.
  • Resolved: Die tatsächlich für das Projekt heruntergeladene Version, die der angegebenen Version entspricht.
  • Latest: Die aktuellste auf NuGet verfügbare Updateversion

Der empfohlene Workflow besteht darin, die folgenden Befehle in dieser Reihenfolge auszuführen:

  1. dotnet list package --outdated ausführen. Dieser Befehl listet alle veralteten Pakete auf. Er stellt Informationen in den Spalten Requested, Resolved und Latest bereit.
  2. dotnet add package <package name> ausführen. Dieser Befehl versucht, ein Update auf die neueste Version durchzuführen. Optional können Sie auch --version=<version number/range> übergeben.