在Blazor服务器中使用DB上下文工厂



我在为服务器端Blazor应用程序设置EF数据库连接时遇到了一些问题。它一直使用标准的DbContext设置,直到我注意到由于Blazor在整个过程中使用相同上下文的性质,连接无法正确关闭的一些问题。我的研究让我考虑了DbContextFactory,但现在IDbContextFactory接口被弃用,取而代之的是IDesignTimeDbContextFactory

我已经建立了一个类来实现接口:

public class FIS2ContextFactory : IDesignTimeDbContextFactory<FIS2_DbContext>
{
private readonly DbContextOptions<FIS2_FranklinContext_AutoGenerated> options;
public FIS2ContextFactory(DbContextOptions<FIS2_FranklinContext_AutoGenerated> contextOptions)
{
options = contextOptions;
}
public FIS2_DbContext CreateDbContext(string[] args)
{
return new FIS2_DbContext(options);
}
}

我想要使用的DbContext是这样的,它继承并扩展了EF Power Tools生成的DbContext:

public partial class FIS2_DbContext : FIS2_FranklinContext_AutoGenerated
{
public FIS2_DbContext()
{
}
public FIS2_DbContext(DbContextOptions<FIS2_FranklinContext_AutoGenerated> options) : base(options)
{
}
public virtual DbSet<StudentBasicDetailsWithCurrentTg> StudentBasicDetailsWithCurrentTgs { get; set; }
public virtual DbSet<CurriculumSearchBasicDetails> CurriculumSearchBasicDetails { get; set; }
public virtual DbSet<StudentAllEnrolments> StudentAllEnrolments { get; set; }
}

在我的startup.cs中,我在ConfigureServices方法中这样设置:

public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<FIS2_DbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("FIS2")));
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<IFileService, FileService>();
services.AddScoped<IEmailService, EmailService>();
services.AddScoped<ITimetableService, TimetableService>();
services.AddScoped<ICurriculumService, CurriculumServiceEf>();
services.AddScoped<IStudentService, StudentServiceEf>();
services.AddScoped<ICollectionService, CollectionsServiceEf>();
services.AddHttpContextAccessor();
services.AddHttpClient();
services.AddAuthenticationCore();
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddAuthorization();
services.AddSyncfusionBlazor();
services.AddScoped<SessionState>();
}

我的问题是,当设置使用此数据库连接的服务时,我会在program.cs:中遇到此错误消息

某些服务无法构建(验证服务描述符"ServiceType:DataLibrary.Data.Interfaces.ITimetableService Lifetime:Scoped ImplementationType:DataLibrary.Data.BusinessLayer.TimetableService"时出错:在尝试激活"DataLibrary.Data.BusinessLayer.TimetableService"的过程中,无法解析类型为"DataLibrary.Models.FIS2Context Factory"的服务。((验证服务描述符"ServiceType:DataLibrary.Data.Interfaces.ICurriculumService生存期:作用域实现类型:DataLibrary.Data.BusinessLayer.CurriculumServiceEf"时出错:在尝试激活"DataLibrary.Models.FIS2ContextFactory"时,无法解析类型为"DataLibraris.Models.FIS2Context Factory"的服务。((验证服务描述符"ServiceType:DataLibrary.Data.Interfaces.IStudentService生存期:作用域实现类型:DataLibrary.Data.BusinessLayer.StudentServiceEf"时出错:在尝试激活"DataLibrary.Data.BusinessLayer.StudentServiceEf"时,无法解析类型为"DataLibrary.Models.FIS2ContextFactory"的服务。((验证服务描述符"ServiceType:DataLibrary.Data.Interfaces.ICollectionService生存期:作用域实现类型:DataLibrary.Data.BusinessLayer.CollectionsServiceEf"时出错:在尝试激活"DataLibrary.Models.FIS2ContextFactory"时,无法解析类型为"DataLibraris.Data.BusinessLayer.CollectionsServicesEf"的服务。(

为了参考,这里有一个如何设置TimetableService的示例(其他示例以相同的方式实例化(:

using DataLibrary.Data.Interfaces;
using DataLibrary.Models;
using DataLibrary.Models.timetable;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace DataLibrary.Data.BusinessLayer
{
public class TimetableService : ITimetableService
{
private FIS2ContextFactory _contextFactory;
public TimetableService(FIS2ContextFactory db)
{
_contextFactory = db;
}
public async Task<List<spGetHolidaysBetweenDatesResult>> GetHolidaysBetweenDatesAsync(DateTime startDate, DateTime endDate)
{
string[] args = { "" };
var _db = _contextFactory.CreateDbContext(args);
var procedures = _db.Procedures;
return await procedures.spGetHolidaysBetweenDatesAsync(startDate, endDate);
}
public async Task<List<PeriodsBetweenDates>> GetPeriodsBetweenDatesAsync(DateTime startDate, DateTime endDate)
{
string[] args = { "" };
var _db = _contextFactory.CreateDbContext(args);
var procedures = _db.Procedures;
var toReturn = new List<PeriodsBetweenDates>();
var results = await procedures.spGetPeriodsBetweenDatesAsync(startDate, endDate);
foreach (var item in results)
{
toReturn.Add(new PeriodsBetweenDates(item.Date, item.Timetable, item.BlockCode, item.StartTime, item.EndTime));
}
return toReturn;
}
public async Task<List<StudentTimetable>> GetStudentTimetableAsync(DateTime startDate, DateTime endDate, string studentID)
{
string[] args = { "" };
var _db = _contextFactory.CreateDbContext(args);
var procedures = _db.Procedures;
var results = await procedures.spGetStudentTimetableAsync(startDate, endDate, studentID);
List<StudentTimetable> studentTimetables = new List<StudentTimetable>();
foreach (var item in results)
{
studentTimetables.Add(JsonConvert.DeserializeObject<StudentTimetable>(item.timetable));
}
return studentTimetables;
}
}
}

是因为我在启动时使用了错误的方法来创建上下文工厂,还是后来出错了?

如果你想解析一个特定的工厂类型,你必须注册这个重载,AddDbContextFactory<TContext,TFactory>记录在这里:

此重载允许要注册的IDbContentFactory,而不是使用EF Core默认出厂时附带。

所以

services.AddDbContextFactory<FIS2_DbContext,FIS2ContextFactory>(options => options.UseSqlServer(Configuration.GetConnectionString("FIS2")));

最新更新