package-management

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

NuGet Package Management

NuGet包管理

When to Use This Skill

何时使用此技能

Use this skill when:
  • Adding, removing, or updating NuGet packages
  • Setting up Central Package Management (CPM) for a solution
  • Managing package versions across multiple projects
  • Troubleshooting package conflicts or restore issues

在以下场景使用此技能:
  • 添加、移除或更新NuGet包时
  • 为解决方案设置Central Package Management (CPM)时
  • 跨多个项目管理包版本时
  • 排查包冲突或还原问题时

Golden Rule: Never Edit XML Directly

黄金准则:切勿直接编辑XML文件

Always use
dotnet
CLI commands to manage packages.
Never manually edit
.csproj
or
Directory.Packages.props
files.
bash
undefined
**请始终使用
dotnet
CLI命令管理包。**切勿手动编辑
.csproj
Directory.Packages.props
文件。
bash
undefined

DO: Use CLI commands

DO: Use CLI commands

dotnet add package Newtonsoft.Json dotnet remove package Newtonsoft.Json dotnet list package --outdated
dotnet add package Newtonsoft.Json dotnet remove package Newtonsoft.Json dotnet list package --outdated

DON'T: Edit XML directly

DON'T: Edit XML directly

<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />


**Why:**
- CLI validates package exists and resolves correct version
- Handles transitive dependencies correctly
- Updates lock files if present
- Avoids typos and malformed XML
- Works correctly with CPM

---

**原因:**
- CLI会验证包是否存在并解析正确版本
- 正确处理传递依赖
- 若存在锁定文件则会更新
- 避免拼写错误和格式错误的XML
- 与CPM兼容

---

Central Package Management (CPM)

Central Package Management (CPM) 集中包管理

CPM centralizes all package versions in one file, eliminating version conflicts across projects.
CPM将所有包版本集中在一个文件中,消除跨项目的版本冲突。

Enable CPM

启用CPM

Create
Directory.Packages.props
in solution root:
xml
<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <ItemGroup>
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageVersion Include="Serilog" Version="4.0.0" />
    <PackageVersion Include="xunit" Version="2.9.2" />
  </ItemGroup>
</Project>
在解决方案根目录创建
Directory.Packages.props
文件:
xml
<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <ItemGroup>
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageVersion Include="Serilog" Version="4.0.0" />
    <PackageVersion Include="xunit" Version="2.9.2" />
  </ItemGroup>
</Project>

Project Files with CPM

使用CPM的项目文件

Projects reference packages without versions:
xml
<!-- src/MyApp/MyApp.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" />
    <PackageReference Include="Serilog" />
  </ItemGroup>
</Project>
项目引用包时无需指定版本
xml
<!-- src/MyApp/MyApp.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" />
    <PackageReference Include="Serilog" />
  </ItemGroup>
</Project>

Adding Packages with CPM

使用CPM添加包

bash
undefined
bash
undefined

Adds to Directory.Packages.props AND project file

Adds to Directory.Packages.props AND project file

dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.Console

Result in Directory.Packages.props:

Result in Directory.Packages.props:

<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />

<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />

Result in project file:

Result in project file:

<PackageReference Include="Serilog.Sinks.Console" />

<PackageReference Include="Serilog.Sinks.Console" />


---

---

Shared Version Variables

共享版本变量

Group related packages with shared version variables:
xml
<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <!-- Shared version variables -->
  <PropertyGroup Label="SharedVersions">
    <AkkaVersion>1.5.59</AkkaVersion>
    <AkkaHostingVersion>1.5.59</AkkaHostingVersion>
    <AspireVersion>9.0.0</AspireVersion>
    <OpenTelemetryVersion>1.11.0</OpenTelemetryVersion>
    <XunitVersion>2.9.2</XunitVersion>
  </PropertyGroup>

  <!-- Akka.NET packages - all use same version -->
  <ItemGroup Label="Akka.NET">
    <PackageVersion Include="Akka" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Cluster.Sharding" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Cluster.Tools" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Persistence" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Streams" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Hosting" Version="$(AkkaHostingVersion)" />
    <PackageVersion Include="Akka.Cluster.Hosting" Version="$(AkkaHostingVersion)" />
  </ItemGroup>

  <!-- Aspire packages -->
  <ItemGroup Label="Aspire">
    <PackageVersion Include="Aspire.Hosting" Version="$(AspireVersion)" />
    <PackageVersion Include="Aspire.Hosting.AppHost" Version="$(AspireVersion)" />
    <PackageVersion Include="Aspire.Hosting.PostgreSQL" Version="$(AspireVersion)" />
    <PackageVersion Include="Aspire.Hosting.Testing" Version="$(AspireVersion)" />
  </ItemGroup>

  <!-- OpenTelemetry packages -->
  <ItemGroup Label="OpenTelemetry">
    <PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="$(OpenTelemetryVersion)" />
    <PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="$(OpenTelemetryVersion)" />
    <PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="$(OpenTelemetryVersion)" />
    <PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="$(OpenTelemetryVersion)" />
  </ItemGroup>

  <!-- Testing -->
  <ItemGroup Label="Testing">
    <PackageVersion Include="xunit" Version="$(XunitVersion)" />
    <PackageVersion Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
    <PackageVersion Include="FluentAssertions" Version="6.12.0" />
    <PackageVersion Include="Verify.Xunit" Version="26.0.0" />
  </ItemGroup>
</Project>
Benefits:
  • Update all Akka packages by changing one variable
  • Clear organization with labeled ItemGroups
  • Prevents version mismatches in related packages

使用共享版本变量对相关包进行分组:
xml
<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <!-- Shared version variables -->
  <PropertyGroup Label="SharedVersions">
    <AkkaVersion>1.5.59</AkkaVersion>
    <AkkaHostingVersion>1.5.59</AkkaHostingVersion>
    <AspireVersion>9.0.0</AspireVersion>
    <OpenTelemetryVersion>1.11.0</OpenTelemetryVersion>
    <XunitVersion>2.9.2</XunitVersion>
  </PropertyGroup>

  <!-- Akka.NET packages - all use same version -->
  <ItemGroup Label="Akka.NET">
    <PackageVersion Include="Akka" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Cluster.Sharding" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Cluster.Tools" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Persistence" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Streams" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Hosting" Version="$(AkkaHostingVersion)" />
    <PackageVersion Include="Akka.Cluster.Hosting" Version="$(AkkaHostingVersion)" />
  </ItemGroup>

  <!-- Aspire packages -->
  <ItemGroup Label="Aspire">
    <PackageVersion Include="Aspire.Hosting" Version="$(AspireVersion)" />
    <PackageVersion Include="Aspire.Hosting.AppHost" Version="$(AspireVersion)" />
    <PackageVersion Include="Aspire.Hosting.PostgreSQL" Version="$(AspireVersion)" />
    <PackageVersion Include="Aspire.Hosting.Testing" Version="$(AspireVersion)" />
  </ItemGroup>

  <!-- OpenTelemetry packages -->
  <ItemGroup Label="OpenTelemetry">
    <PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="$(OpenTelemetryVersion)" />
    <PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="$(OpenTelemetryVersion)" />
    <PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="$(OpenTelemetryVersion)" />
    <PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="$(OpenTelemetryVersion)" />
  </ItemGroup>

  <!-- Testing -->
  <ItemGroup Label="Testing">
    <PackageVersion Include="xunit" Version="$(XunitVersion)" />
    <PackageVersion Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
    <PackageVersion Include="FluentAssertions" Version="6.12.0" />
    <PackageVersion Include="Verify.Xunit" Version="26.0.0" />
  </ItemGroup>
</Project>
优势:
  • 修改一个变量即可更新所有Akka包
  • 通过带标签的ItemGroup实现清晰的组织
  • 避免相关包出现版本不匹配的问题

When NOT to Use CPM

何时不使用CPM

Central Package Management isn't always the right choice:
集中包管理并非在所有场景下都适用:

Legacy Projects

遗留项目

Migrating an existing large solution to CPM can introduce issues:
  • Existing version conflicts become visible all at once
  • Some packages may have intentional version differences
  • Migration requires touching many files simultaneously
Recommendation: For legacy projects, migrate incrementally or stick with per-project versioning if it's working.
将现有大型解决方案迁移到CPM可能会引发问题:
  • 现有的版本冲突会一次性全部显现
  • 某些包可能有意使用不同版本
  • 迁移需要同时修改大量文件
建议:对于遗留项目,可逐步迁移;若当前的按项目版本管理方式运行正常,可继续使用。

Version Ranges

版本范围

CPM requires exact versions - it doesn't support version ranges:
xml
<!-- NOT supported with CPM -->
<PackageVersion Include="Newtonsoft.Json" Version="[13.0,14.0)" />

<!-- Must use exact version -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
If you need version ranges (rare, but some library scenarios require it), CPM won't work.
CPM要求使用精确版本——不支持版本范围:
xml
<!-- NOT supported with CPM -->
<PackageVersion Include="Newtonsoft.Json" Version="[13.0,14.0)" />

<!-- Must use exact version -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
如果您需要使用版本范围(这种情况很少见,但某些库场景下需要),则CPM不适用。

Older .NET Versions

旧版.NET版本

CPM requires:
  • .NET SDK 6.0.300+ or later
  • NuGet 6.2+ or later
  • Visual Studio 2022 17.2+ or later
If you're targeting older SDK versions or have team members on older tooling, CPM may cause build failures.
CPM需要满足以下条件:
  • **.NET SDK 6.0.300+**或更高版本
  • **NuGet 6.2+**或更高版本
  • **Visual Studio 2022 17.2+**或更高版本
如果您的项目目标是旧版SDK,或者团队成员使用旧版工具,CPM可能会导致构建失败。

Multi-Repo Solutions

多仓库解决方案

If your solution spans multiple repositories that are built independently, CPM's single
Directory.Packages.props
won't help - each repo needs its own.

如果您的解决方案跨越多个独立构建的仓库,CPM的单个
Directory.Packages.props
文件无法发挥作用——每个仓库需要自己的配置文件。

CLI Command Reference

CLI命令参考

Adding Packages

添加包

bash
undefined
bash
undefined

Add latest stable version

Add latest stable version

dotnet add package Serilog
dotnet add package Serilog

Add specific version

Add specific version

dotnet add package Serilog --version 4.0.0
dotnet add package Serilog --version 4.0.0

Add prerelease

Add prerelease

dotnet add package Serilog --prerelease
dotnet add package Serilog --prerelease

Add to specific project

Add to specific project

dotnet add src/MyApp/MyApp.csproj package Serilog
undefined
dotnet add src/MyApp/MyApp.csproj package Serilog
undefined

Removing Packages

移除包

bash
undefined
bash
undefined

Remove from current project

Remove from current project

dotnet remove package Serilog
dotnet remove package Serilog

Remove from specific project

Remove from specific project

dotnet remove src/MyApp/MyApp.csproj package Serilog
undefined
dotnet remove src/MyApp/MyApp.csproj package Serilog
undefined

Listing Packages

列出包

bash
undefined
bash
undefined

List all packages in solution

List all packages in solution

dotnet list package
dotnet list package

Show outdated packages

Show outdated packages

dotnet list package --outdated
dotnet list package --outdated

Include transitive dependencies

Include transitive dependencies

dotnet list package --include-transitive
dotnet list package --include-transitive

Show vulnerable packages

Show vulnerable packages

dotnet list package --vulnerable
dotnet list package --vulnerable

Show deprecated packages

Show deprecated packages

dotnet list package --deprecated
undefined
dotnet list package --deprecated
undefined

Updating Packages

更新包

bash
undefined
bash
undefined

With CPM: Edit the version in Directory.Packages.props

With CPM: Edit the version in Directory.Packages.props

Then restore to apply

Then restore to apply

dotnet restore
dotnet restore

Without CPM: Remove and add with new version

Without CPM: Remove and add with new version

dotnet remove package Serilog dotnet add package Serilog --version 4.1.0
dotnet remove package Serilog dotnet add package Serilog --version 4.1.0

Or use dotnet-outdated tool (recommended)

Or use dotnet-outdated tool (recommended)

dotnet tool install --global dotnet-outdated-tool dotnet outdated --upgrade
undefined
dotnet tool install --global dotnet-outdated-tool dotnet outdated --upgrade
undefined

Restore and Clean

还原与清理

bash
undefined
bash
undefined

Restore packages

Restore packages

dotnet restore
dotnet restore

Clear local cache (troubleshooting)

Clear local cache (troubleshooting)

dotnet nuget locals all --clear
dotnet nuget locals all --clear

Force restore (ignore cache)

Force restore (ignore cache)

dotnet restore --force

---
dotnet restore --force

---

Package Sources

包源

List Sources

列出源

bash
dotnet nuget list source
bash
dotnet nuget list source

Add Private Feed

添加私有源

bash
undefined
bash
undefined

Add authenticated feed

Add authenticated feed

dotnet nuget add source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json
--name MyFeed
--username az
--password $PAT
--store-password-in-clear-text
undefined
dotnet nuget add source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json
--name MyFeed
--username az
--password $PAT
--store-password-in-clear-text
undefined

NuGet.config

NuGet.config

For solution-specific sources, create
NuGet.config
:
xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
    <add key="MyPrivateFeed" value="https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json" />
  </packageSources>
  <packageSourceCredentials>
    <MyPrivateFeed>
      <add key="Username" value="az" />
      <add key="ClearTextPassword" value="%NUGET_PAT%" />
    </MyPrivateFeed>
  </packageSourceCredentials>
</configuration>

针对特定解决方案的源,创建
NuGet.config
文件:
xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
    <add key="MyPrivateFeed" value="https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json" />
  </packageSources>
  <packageSourceCredentials>
    <MyPrivateFeed>
      <add key="Username" value="az" />
      <add key="ClearTextPassword" value="%NUGET_PAT%" />
    </MyPrivateFeed>
  </packageSourceCredentials>
</configuration>

Common Patterns

常见模式

Development-Only Packages

仅开发环境包

xml
<!-- Directory.Packages.props -->
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />

<!-- Project file - mark as development dependency -->
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
xml
<!-- Directory.Packages.props -->
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />

<!-- Project file - mark as development dependency -->
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />

Conditional Packages

条件包

xml
<!-- Only include in Debug builds -->
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
  <PackageReference Include="JetBrains.Annotations" />
</ItemGroup>

<!-- Platform-specific -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
  <PackageReference Include="System.Text.Json" />
</ItemGroup>
xml
<!-- Only include in Debug builds -->
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
  <PackageReference Include="JetBrains.Annotations" />
</ItemGroup>

<!-- Platform-specific -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
  <PackageReference Include="System.Text.Json" />
</ItemGroup>

Version Override (Escape Hatch)

版本覆盖(应急方案)

When you must override CPM for one project (rare):
xml
<!-- Project file - use sparingly! -->
<PackageReference Include="Newtonsoft.Json" VersionOverride="12.0.3" />
Warning: This is detected by Slopwatch (see
dotnet/slopwatch
skill) as potential slop.

当您必须为单个项目覆盖CPM配置时(这种情况很少见):
xml
<!-- Project file - use sparingly! -->
<PackageReference Include="Newtonsoft.Json" VersionOverride="12.0.3" />
警告:Slopwatch(请查看
dotnet/slopwatch
技能)会将此检测为潜在的不良实践。

Troubleshooting

排查问题

Version Conflicts

版本冲突

bash
undefined
bash
undefined

See full dependency tree

See full dependency tree

dotnet list package --include-transitive
dotnet list package --include-transitive

Find what's pulling in a specific package

Find what's pulling in a specific package

dotnet list package --include-transitive | grep -i "PackageName"
undefined
dotnet list package --include-transitive | grep -i "PackageName"
undefined

Restore Failures

还原失败

bash
undefined
bash
undefined

Clear all caches

Clear all caches

dotnet nuget locals all --clear
dotnet nuget locals all --clear

Restore with detailed logging

Restore with detailed logging

dotnet restore --verbosity detailed
dotnet restore --verbosity detailed

Check for locked packages

Check for locked packages

cat packages.lock.json
undefined
cat packages.lock.json
undefined

Lock Files

锁定文件

For reproducible builds, use package lock files:
xml
<!-- Directory.Build.props -->
<PropertyGroup>
  <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>
Then commit
packages.lock.json
files.

为了实现可复现的构建,请使用包锁定文件:
xml
<!-- Directory.Build.props -->
<PropertyGroup>
  <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>
然后提交
packages.lock.json
文件。

Anti-Patterns

反模式

Don't: Edit XML Directly

切勿:直接编辑XML文件

xml
<!-- BAD: Manual XML editing -->
<PackageReference Include="Typo.Package" Version="1.0.0" />
<!-- Package might not exist! CLI would catch this. -->
xml
<!-- BAD: Manual XML editing -->
<PackageReference Include="Typo.Package" Version="1.0.0" />
<!-- Package might not exist! CLI would catch this. -->

Don't: Inline Versions with CPM

切勿:在CPM中使用内联版本

xml
<!-- BAD: Bypasses CPM -->
<PackageReference Include="Serilog" Version="4.0.0" />

<!-- GOOD: Version comes from Directory.Packages.props -->
<PackageReference Include="Serilog" />
xml
<!-- BAD: Bypasses CPM -->
<PackageReference Include="Serilog" Version="4.0.0" />

<!-- GOOD: Version comes from Directory.Packages.props -->
<PackageReference Include="Serilog" />

Don't: Mix Version Management

切勿:混合版本管理方式

xml
<!-- BAD: Some versions in CPM, some inline -->
<PackageReference Include="Serilog" />  <!-- From CPM -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />  <!-- Inline -->
xml
<!-- BAD: Some versions in CPM, some inline -->
<PackageReference Include="Serilog" />  <!-- From CPM -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />  <!-- Inline -->

Don't: Forget Shared Variables

切勿:忘记使用共享变量

xml
<!-- BAD: Related packages with different versions -->
<PackageVersion Include="Akka" Version="1.5.59" />
<PackageVersion Include="Akka.Cluster" Version="1.5.58" />  <!-- Mismatch! -->

<!-- GOOD: Use shared variable -->
<PackageVersion Include="Akka" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />

xml
<!-- BAD: Related packages with different versions -->
<PackageVersion Include="Akka" Version="1.5.59" />
<PackageVersion Include="Akka.Cluster" Version="1.5.58" />  <!-- Mismatch! -->

<!-- GOOD: Use shared variable -->
<PackageVersion Include="Akka" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />

Quick Reference

快速参考

TaskCommand
Add package
dotnet add package <name>
Add specific version
dotnet add package <name> --version <ver>
Remove package
dotnet remove package <name>
List packages
dotnet list package
Show outdated
dotnet list package --outdated
Show vulnerable
dotnet list package --vulnerable
Restore
dotnet restore
Clear cache
dotnet nuget locals all --clear

任务命令
添加包
dotnet add package <name>
添加指定版本
dotnet add package <name> --version <ver>
移除包
dotnet remove package <name>
列出包
dotnet list package
显示过时包
dotnet list package --outdated
显示存在漏洞的包
dotnet list package --vulnerable
还原包
dotnet restore
清理缓存
dotnet nuget locals all --clear

Resources

参考资源