部署Linux的.NET6应用EF Core查PostgreSQL时Npgsql程序集缺失报错
问题:.NET 6 + PostgreSQL部署Linux后出现Npgsql程序集找不到错误
问题背景
基于.NET 6和PostgreSQL开发了定时后台服务(Hosted Service),定期调用仓储方法查询数据库实体,仓储代码如下:
public class NotificationRepository : INotificationRepository { public async Task<List<Notification>> GetUnreadDeviceNotifications() { using var context = new MyDbContext(); return await context.Notifications.Where(x => !x.IsSentTimestamp.HasValue && x.ChannelId == 8).ToListAsync(); } }
应用在Windows环境运行正常,但部署到Linux机器后,每次调用GetUnreadDeviceNotifications都会触发错误。
错误日志
Aug 07 12:50:46 my-app my-app.Web[1432629]: System.IO.FileNotFoundException: Could not load file or assembly 'Npgsql, Version=6.0.8.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7'. The system cannot find the file specified. Aug 07 12:50:46 my-app my-app.Web[1432629]: File name: 'Npgsql, Version=6.0.8.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7' Aug 07 12:50:46 my-app my-app.Web[1432629]: at Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.NpgsqlOptionsExtension.ExtensionInfo.GetServiceProviderHashCode() Aug 07 12:50:46 my-app my-app.Web[1432629]: at Microsoft.EntityFrameworkCore.DbContextOptions.GetHashCode() Aug 07 12:50:46 my-app my-app.Web[1432629]: at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd[TArg](TKey key, Func`3 valueFactory, TArg factoryArgument) Aug 07 12:50:46 my-app my-app.Web[1432629]: at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.GetOrAdd(IDbContextOptions options, Boolean providerRequired) Aug 07 12:50:46 my-app my-app.Web[1432629]: at Microsoft.EntityFrameworkCore.DbContext.get_ContextServices() Aug 07 12:50:46 my-app my-app.Web[1432629]: at Microsoft.EntityFrameworkCore.DbContext.get_Model() Aug 07 12:50:46 my-app my-app.Web[1432629]: at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType() Aug 07 12:50:46 my-app my-app.Web[1432629]: at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable() Aug 07 12:50:46 my-app my-app.Web[1432629]: at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider() Aug 07 12:50:46 my-app my-app.Web[1432629]: at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate) Aug 07 12:50:46 my-app my-app.Web[1432629]: at my-app.Infrastructure.Repositories.NotificationRepository.GetUnreadDeviceNotifications() in C:\Projects\my-app\src\my-app.Infrastructure\Repositories\NotificationRepository.cs:line 22 Aug 07 12:50:46 my-app my-app.Web[1432629]: at my-app.Application.Services.MessagingServices.NotificationReadingService.DoWork(Object state) in C:\Projects\my-app\src\my-app.Application\Services\MessagingServices\NotificationReadingService.cs:line 35
项目依赖项
<ItemGroup> <PackageReference Include="Dapper" Version="2.0.123" /> <PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="10.0.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" /> <PackageReference Include="Npgsql" Version="6.0.3" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.3" /> </ItemGroup>
解决方案
1. 统一Npgsql依赖版本,解决版本冲突
错误提示需要Npgsql 6.0.8.0,但项目引用的是6.0.3,说明存在间接依赖拉高版本的情况,导致部署时缺失对应版本程序集:
- 直接将
Npgsql和Npgsql.EntityFrameworkCore.PostgreSQL升级到同一稳定版本(比如6.0.8,或与EF Core 6.0.3兼容的最新版本),确保版本完全一致。 - 或者在项目文件中添加版本绑定,强制所有依赖使用指定版本:
<ItemGroup> <PackageReference Include="Npgsql" Version="6.0.3" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.3" /> <!-- 强制绑定版本,避免间接依赖升级 --> <PackageReference Include="Npgsql" Version="6.0.3" PrivateAssets="All" /> </ItemGroup>
2. 检查Linux发布配置
- 发布时使用框架依赖或自包含模式,确保所有依赖被正确复制:
# 框架依赖发布 dotnet publish -c Release -r linux-x64 --self-contained false # 自包含发布(无需目标机器安装.NET运行时) dotnet publish -c Release -r linux-x64 --self-contained true
- 检查发布输出目录是否存在
Npgsql.dll,若缺失,清理Nuget缓存后重新发布:
dotnet nuget locals all --clear dotnet restore dotnet publish -c Release -r linux-x64
3. 修复DbContext创建方式
当前直接new MyDbContext未使用依赖注入,可能导致配置或依赖加载异常,改为构造函数注入:
public class NotificationRepository : INotificationRepository { private readonly MyDbContext _context; public NotificationRepository(MyDbContext context) { _context = context; } public async Task<List<Notification>> GetUnreadDeviceNotifications() { return await _context.Notifications.Where(x => !x.IsSentTimestamp.HasValue && x.ChannelId == 8).ToListAsync(); } }
在Program.cs中注册DbContext和仓储:
builder.Services.AddDbContext<MyDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("YourConnectionString"))); builder.Services.AddScoped<INotificationRepository, NotificationRepository>();
4. 验证Linux环境.NET运行时版本
确保Linux机器上安装的.NET 6运行时版本与开发环境兼容,执行dotnet --version查看版本,若版本过低则升级到对应版本。
内容的提问来源于stack exchange,提问作者Kęstutis Ramulionis
相关产品推荐
相关产品推荐

