仓库基类无法直接使用(最好不要直接使用),需要根据模型创建具体的仓库类。
在Repositories文件夹下创建4个类文件:
以MajorRepo为例。
首先通过冒号继承BaseRepository,并指定Major作为泛型的具体类。
代码如下:
public class MajorRepo : BaseRepository<Major>
{
}
其次,由于BaseRepository需要有一个带参数的构造函数注入AppDbContext的实例,因此MajorRepo也需要有一个同样参数列表的构造函数。
代码如下:
public class MajorRepo(AppDbContext context) : BaseRepository<Major>
{
}
最后,需要将构造函数的参数传递给基类,这样,在创建MajorRepo的实例时,就可以将AppDbContext的实例传递给父类BaseRepository。
代码如下:
public class MajorRepo(AppDbContext context) : BaseRepository<Major>(context)
{
}
至此Major的仓库类就可以使用了。
其他模型的仓库类代码如下所示:
GradeRepo.cs
public class GradeRepo(AppDbContext context) : BaseRepository<Grade>(context)
{
}
ClassRepo.cs
public class ClassRepo(AppDbContext context) : BaseRepository<Class>(context)
{
}
StudentRepo.cs
public class StudentRepo(AppDbContext context) : BaseRepository<Student>(context)
{
}
为了更加方便地让其他组件获取仓库实例,可以将仓库注册为服务。
具体方法是在Program.cs中通过AddScoped方法将仓库添加为服务。
代码如下:
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
IServiceCollection services = builder.Services;
services.AddControllersWithViews();
services.AddDbContext<AppDbContext>();
services.AddScoped<MajorRepo>();
services.AddScoped<GradeRepo>();
services.AddScoped<ClassRepo>();
services.AddScoped<StudentRepo>();
var app = builder.Build();
app.UseStaticFiles();
app.MapDefaultControllerRoute();
app.Run();
}
这样就相当于将MajorRepo这四个仓库类放到一个货架上,等待顾客下单。
除了AddScoped方法,还有2个方法可以将类注册为服务,分别是AddTransient和AddSingleton。
如果将类比喻成商品,那么Singleton、Scoped和AddTransient就相当于它们的保质期。
Singleton:保质期最长,随着项目的启动而产生,随着项目的关闭而消亡。
Scoped:保质期一般,在一次用户的请求内产生和消亡。
AddTransient:保质期极短,在产生后完成使命后便消失了。
Question:
为什么不将MajorRepo等仓库类注册为保质期最长的Singleton服务?
因为AddDbContext会将AppDbContext注册为Scoped类型的服务。
而MajorRepo中依赖AppDbContext,因此MajorRepo的保质期不能设置得比Scoped长,只能保持一致或更短。
还是换成商品来举例,一件商品的保质期不可能比它的配料的保质期长,因为配料坏了,商品也就坏了。
在这里MajorRepo就相当于商品,而AppDbContext相当于配料。