我偶尔会从Blazor服务器端的.NET Core项目中得到这个错误。
无法从传输连接读取数据:现有远程主机强制关闭了连接。。
重新加载页面或再次尝试执行相同的函数调用后,将不会出现错误,结果将返回
DbContext定义如下所示:
public class ADPortalDbContext:DbContext
{
public DbSet<Company> Companies { get; set; }
public ADPortalDbContext(DbContextOptions<ADPortalDbContext> options)
: base(options) { }
}
从数据库返回结果的服务如下所示:
公共类CompanyService:ICompanyService{专用只读ADPortalDbContext上下文;
public CompanyService(ADPortalDbContext context)
{
this.context = context;
}
public async Task<IEnumerable<Company>> GetCompaniesSearchText(string searchText)
{
try
{
return await context.Companies
.Where(i => EF.Functions.Like(i.Name.ToLower(), $"%{searchText.ToLower()}%"))
.ToListAsync()
.ConfigureAwait(false);
}
catch(Exception ex)
{
throw new InvalidOperationException("Unable to return results " + ex.Message);
}
}
Blazor应用程序的Startup.cs如下所示:
services.AddTransient<ICompanyService, CompanyService>();
services.AddDbContext<ADPortalDbContext>(options =>
options.UseMySql(connStr, srvVersion, x =>
{
x.MigrationsAssembly("DCPortal.Infrastructre");
}),
contextLifetime: ServiceLifetime.Transient);
调用该服务的Blazor页面如下所示:
@inject ICompanyService CompanyService
private async Task<IEnumerable<Company>> SearchCompanies(string searchText)
{
try
{
IEnumerable<Company> companies_ListDb = await CompanyService.GetCompaniesSearchText(searchText);
}
catch(Exception ex)
{
//Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..
}
}
问题的一般症结在于服务的生存期——DB上下文应该是一次性的;所以在后台,连接在某个时刻被关闭(导致您的错误(。
我发现绕过它的唯一真正方法是实现上下文工厂。
因此,在您的情况下,您将希望在与上下文相同的区域中创建一个文件:
public class ADPortalDbContextFactory : IDbContextFactory<ADPortalDbContext>
{
private readonly DbContextOptions<ADPortalDbContext> options;
public ADPortalDbContextFactory(DbContextOptions<ADPortalDbContext> contextOptions)
{
options = contextOptions;
}
public ADPortalDbContext CreateDbContext()
{
return new ADPortalDbContext(options);
}
}
从那里,你可以对你的创业进行一个简单的调整:
services.AddDbContext<ADPortalDbContext>(options =>
options.UseMySql(connStr, srvVersion, x =>
{
x.MigrationsAssembly("DCPortal.Infrastructre");
}));
services.AddDbContextFactory<ADPortalDbContext, ADPortalDbContextFactory>(options =>
options.UseMySql(connStr, srvVersion, x =>
{
x.MigrationsAssembly("DCPortal.Infrastructre");
}), ServiceLifetime.Scoped);
services.AddScoped<ICompanyService, CompanyService>();
然后您的服务变成:
public class CompanyService : ICompanyService
{
private readonly IDbContextFactory<ADPortalDbContext> contextFactory;
public CompanyService(IDbContextFactory<ADPortalDbContext> context)
{
this.contextFactory = context;
}
public async Task<IEnumerable<Company>> GetCompaniesSearchText(string searchText)
{
try
{
using (var context = contextFactory.CreateDbContext())
{
return await context.Companies
.Where(i => EF.Functions.Like(i.Name.ToLower(), $"%{searchText.ToLower()}%"))
.ToListAsync()
.ConfigureAwait(false);
}
}
catch(Exception ex)
{
throw new InvalidOperationException("Unable to return results " + ex.Message);
}
}
}