【发布时间】:2022-01-07 06:47:18
【问题描述】:
我在为服务器端 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”类型的服务.Models.FIS2ContextFactory',同时尝试激活'DataLibrary.Data.BusinessLayer.TimetableService'。)(验证服务描述符'ServiceType:DataLibrary.Data.Interfaces.ICurriculumService Lifetime:Scoped ImplementationType:DataLibrary.Data.BusinessLayer.CurriculumServiceEf'时出错:尝试激活“DataLibrary.Data.BusinessLayer.CurriculumServiceEf”时,无法解析“DataLibrary.Models.FIS2ContextFactory”类型的服务。)(验证服务描述符“ServiceType:DataLibrary.Data.Interfaces.ISTudentService Lifetime:Scoped ImplementationType”时出错:DataLibrary.Data.BusinessLayer.StudentServiceEf':无法解析“DataLibrary.Model”类型的服务s.FIS2ContextFactory',同时尝试激活'DataLibrary.Data.BusinessLayer.StudentServiceEf'。)(验证服务描述符'ServiceType:DataLibrary.Data.Interfaces.ICollectionService Lifetime:Scoped ImplementationType:DataLibrary.Data.BusinessLayer.CollectionsServiceEf'时出错:尝试激活“DataLibrary.Data.BusinessLayer.CollectionsServiceEf”时无法解析“DataLibrary.Models.FIS2ContextFactory”类型的服务。)
作为参考,这里是一个如何设置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;
}
}
}
是因为我在启动时使用了错误的方法来创建上下文工厂,还是后来我弄错了?
【问题讨论】:
标签: entity-framework dependency-injection entity-framework-core blazor-server-side dbcontext