繁体   English   中英

实体框架语法与 DBset 混淆

[英]Entity framework syntax confusion with DBset

我目前正在关注 C# 教程,它有这个 ApplicationDbContext class 文件:

public class ApplicationDbContext: DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) {}
public DbSet<Category> Category { get; set; }   
}

其中类别定义为:

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”的数据库表。 我的困惑在于如何在这里声明所有内容。 带有 DbSet 的行 DbContext 文件似乎没有实例化任何东西,而只是将 Category 定义为类型为 DbSet 的公共变量,但随后 IEnumerable 似乎将 Category 视为正在遍历表,调用 _db.Category 也是如此。 在这种情况下,查看代码,类别 class 是被引用的,而不是类别数据库表。 这里的一切是如何联系在一起的?

带有 DbSet 的行 DbContext 文件似乎没有实例化任何东西,而只是将 Category 定义为类型为 DbSet 的公共变量

正确的

那么 IEnumerable 似乎将 Category 视为它正在通过表格

也正确。 Program.cs中的代码将两者联系在一起。 首先,它通过调用AddDbContext<ApplicationDbContext>()启用_db的依赖注入; 其次,它指示_dbDefaultConnection中定义的源(通常是数据库)检索数据。 您应该在appsettings.json中有这个定义 - 例如,

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=servername;Initial Catalog=dbname;User ID=username;password=password;"
  }
}

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

  • DbContext是此数据库模式定义的基础 class。

Category是一个数据Model ,就其本身而言,它只是另一个代表某些东西的 class ...但是当您通过DbSet<Cateogry>类型在DbContext中使用它时,它就变成了一个表定义。 当您阅读此行时:

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

将其解释为: Table called CategoryName that the structure of the CategoryType class.

到目前为止,一切都很好,

下一点与称为依赖注入的概念有关。 这个想法是我们可以在全局级别定义一组指令,这些指令描述如何实例化我们需要在整个应用程序中大量使用的对象,而无需将实例化逻辑放在任何地方。 这是一种定义此逻辑一次的方法,并且与DRY 主体内联。

  • 您可能认为class的构造器是此类信息的合适位置,并且在 DI 之前这是一个常见的选项,但对于复杂类型,这通常需要大量特定于当前应用程序的外部领域知识,这使得很难在其他应用程序或上下文中重用您的类。 DI 是一个优雅的解决方案,它迫使您完全脱离类型的定义和实现。

  • 在构造函数之后(以及在 DI 之前),下一个常见的实现是使用工厂模式使用特定领域的逻辑来创建对象。 认为 DI 是Factory Pattern特定实现。

因此在 Porgram.cs 中,以下代码使用AddDbContext工厂为 DI注册ApplicationDbContext类型。

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

魔法现在发生在您的 DI 堆栈的 rest 中,在这种情况下,我认为您有一个名为IndexModel存储库,稍后您可能会在 Program.cs 中发现更多与该 class 相关的 DI 注册,但想法是,当IndexModel必需的,DI 将调用 class 上的构造函数。

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

由于它需要ApplicationDbContext的实例并且 DI知道如何创建该类型的实例,因此它使用AddDbContext工厂创建ApplicationDbContext的新实例并将其作为参数传递给IndexModel构造函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM