我目前正在学习一个C#教程,它有这样一个ApplicationDbContext类文件:

public class ApplicationDbContext: DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) {}

    public DbSet<Category> Category { get; set; }   
}

其中,Category定义为:

public class Category
{
    [Key]
    public int ID { get; set; }

    [Required]
    public string Name { get; set; }

    public int DisplayOrder { get; set; }
}

它随后被这样引用:

    private readonly ApplicationDbContext _db;

    public IEnumerable<Category> Categories { get; set; }

    public IndexModel(ApplicationDbContext db)
    {
        _db = db;
    }

    public void OnGet()
    {
        Categories = _db.Category;
    }

我在Program.cs文件中也有这个代码:

  builder.Services.AddDbContext<ApplicationDbContext>(options => 
  options.UseSqlServer(
    builder.Configuration.GetConnectionString("DefaultConnection")
  ));

最后一条信息是,我进行了一次迁移,创建了一个名为Category的数据库表.

我的困惑在于这里是如何声明所有内容的;DbContext文件中包含DbSet的行似乎没有实例化任何内容,而只是将Category定义为类型为DbSet<Category>的公共变量,但随后IEnumerable<Category>似乎将Category视为遍历表,调用_db.Category也是如此.

在本例中,纵观代码,引用的是Category类,而不是Category数据库表.这里的一切是怎么联系在一起的?

推荐答案

ApplicationDbContext只是数据上下文的definition.这有效地定义了数据库中的tables.每个DbSet<T>代表数据架构中的一个表.

  • DbContext是该数据库模式定义的基类.

Category是一个数据Model,就它本身而言,它只是代表something的另一个类……但当您通过DbSet<Cateogry>类型在DbContext中使用它时,它就变成了一个表定义.当你读到这句话时:

public DbSet<CategoryType> CategoryName { get; set; } 

请这样解释:Table called CategoryName that the structure of the CategoryType class.

到目前一切尚好,

接下来的这一点与一个名为100的概念有关.我们的 idea 是,我们可以在全局级别定义一组指令,这些指令描述如何实例化我们在整个应用程序中需要大量使用的对象,而不会将实例化逻辑放在任何地方.它是一种定义此逻辑的方法,并且与DRY principal一致.

  • 您可能认为类的contructor是这种类型信息的合适位置,在依赖注入之前,这是一个常见的选项,但对于复杂类型,这通常需要大量特定于当前应用程序的外部领域知识,这使得很难在其他应用程序或上下文中重用您的类.对于这个问题,DI是一个完美的解决方案,它迫使您完全脱离类型的定义和实现.

  • 在构造器之后(在DI之前),下一个常见的实现是使用Factory Pattern使用域特定逻辑创建对象.想想DI是specific实现的Factory Pattern.

因此,在Porgram.cs中,下面的代码是registering-ApplicationDbContext类型的DI,使用AddDbContext-factory.

builder.Services.AddDbContext<ApplicationDbContext>(options => 
options.UseSqlServer(
  builder.Configuration.GetConnectionString("DefaultConnection")
));
  • 注册的一部分是指定连接字符串,在本例中,它告诉底层的factory方法从配置文件中获取连接字符串.

magic现在出现在DI堆栈的其余部分中,在这种情况下,我认为您有一个称为IndexModelrepository,您可能会在稍后的Program.cs中发现,有更多与该类相关的DI注册,但其 idea 是,当IndexModelneeded时,DI将调用该类的构造函数.

public class IndexModel
{
    public IndexModel(ApplicationDbContext db) { ... }
}

因为它需要ApplicationDbContext的实例和DI knows如何创建该类型的实例,所以它使用AddDbContext工厂来创建ApplicationDbContext的新实例,并将其作为参数传递给IndexModel构造函数.

Csharp相关问答推荐

C#自定义字典与JSON(de—)serialize

EF Core. Income和. AsNoTracking正确用法

如何在没有前缀和可选后缀的情况下获取Razor Page Handler方法名称?

方法从数据表中只 Select 一个条件?

Unix上的.NET(核心):.NET意外地未看到通过P/Invoke系统调用对环境变量进行的进程内修改

取决于您的数据量的多个嵌套循环

是否有必要在ASP.NET Core中注册可传递依赖项?

依赖项注入、工厂方法和处置困境

当试图限制EF Select 的列时,如何避免重复代码?

如何在CSharp中将json字符串转换为DataTable?

在try 使用访问服务器上的文件夹时,如何解决CORS错误.NET核心API

如何在onNext之前等待订阅者完成?

Celler ArgumentExpression是否期望在所有情况下都捕获允许空值的运算符?

当try 测试具有协变返回类型的抽象属性时,类似功能引发System.ArgumentException

在使用AWS SDK for.NET时,如何判断S3是否已验证我的对象的校验和?

如何让游戏对象在切换场景时被销毁,但在开始新游戏时重新锁定

C# Winforms:从对象树到TreeView的递归转换重复条目

C#Microsoft.CodeAnalysis.CSharp.Scriiting不等待并行.对于

用MongoDB c#驱动程序删除和返回嵌套数组中的文档

C#静态抽象属性不能被子接口覆盖