仓库类

仓库基类无法直接使用(最好不要直接使用),需要根据模型创建具体的仓库类。

创建仓库类

在Repositories文件夹下创建4个类文件:

  • MajorRepo.cs
  • GradeRepo.cs
  • ClassRepo.cs
  • StudentRepo.cs

继承仓库基类

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个方法可以将类注册为服务,分别是AddTransientAddSingleton

如果将类比喻成商品,那么SingletonScopedAddTransient就相当于它们的保质期。

Singleton:保质期最长,随着项目的启动而产生,随着项目的关闭而消亡。

Scoped:保质期一般,在一次用户的请求内产生和消亡。

AddTransient:保质期极短,在产生后完成使命后便消失了。

Question:

为什么不将MajorRepo等仓库类注册为保质期最长的Singleton服务?

因为AddDbContext会将AppDbContext注册为Scoped类型的服务。

MajorRepo中依赖AppDbContext,因此MajorRepo的保质期不能设置得比Scoped长,只能保持一致更短

还是换成商品来举例,一件商品的保质期不可能比它的配料的保质期长,因为配料坏了,商品也就坏了。

在这里MajorRepo就相当于商品,而AppDbContext相当于配料。