简体   繁体   English

实体框架语法与 DBset 混淆

[英]Entity framework syntax confusion with DBset

I'm currently following a C# tutorial, and it has this ApplicationDbContext class file:我目前正在关注 C# 教程,它有这个 ApplicationDbContext class 文件:

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

Where Category is defined as:其中类别定义为:

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

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

    public int DisplayOrder { get; set; }
}

Which is then later referenced like so:然后像这样引用它:

    private readonly ApplicationDbContext _db;

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

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

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

I also have this in the Program.cs file:我在 Program.cs 文件中也有这个:

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

The final piece of info is that I did a migration to create a database table called "Category".最后一条信息是我进行了迁移以创建一个名为“Category”的数据库表。 My confusion is around how everything is declared here;我的困惑在于如何在这里声明所有内容。 the line DbContext file with DbSet doesn't seem to instantiate anything and instead just defines Category as a public variable with type DbSet, but then the IEnumerable seems to treat Category as if it's going through the table, as does calling _db.Category.带有 DbSet 的行 DbContext 文件似乎没有实例化任何东西,而只是将 Category 定义为类型为 DbSet 的公共变量,但随后 IEnumerable 似乎将 Category 视为正在遍历表,调用 _db.Category 也是如此。 In this case, looking through the code, the Category class is what gets referenced and not the Category database table.在这种情况下,查看代码,类别 class 是被引用的,而不是类别数据库表。 is How does everything tie together here?这里的一切是如何联系在一起的?

the line DbContext file with DbSet doesn't seem to instantiate anything and instead just defines Category as a public variable with type DbSet带有 DbSet 的行 DbContext 文件似乎没有实例化任何东西,而只是将 Category 定义为类型为 DbSet 的公共变量

Correct正确的

then the IEnumerable seems to treat Category as if it's going through the table那么 IEnumerable 似乎将 Category 视为它正在通过表格

Also correct.也正确。 the code in Program.cs ties the two together. Program.cs中的代码将两者联系在一起。 First, it enables Dependency Injection of _db by calling AddDbContext<ApplicationDbContext>() ;首先,它通过调用AddDbContext<ApplicationDbContext>()启用_db的依赖注入; and second, it directs _db to retrieve data from the source (usually, database) defined in DefaultConnection .其次,它指示_dbDefaultConnection中定义的源(通常是数据库)检索数据。 You should have this definition in appsettings.json - for example,您应该在appsettings.json中有这个定义 - 例如,

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

The ApplicationDbContext is just the definition of the data context. ApplicationDbContext只是数据上下文的定义 This effectively defines the tables in your database.这有效地定义了数据库中的 Each DbSet<T> represents a table in your data schema.每个DbSet<T>代表数据架构中的一个表。

  • DbContext is the base class of this database schema definition. DbContext是此数据库模式定义的基础 class。

Category is a data Model , on it's own, it is just another class that represents something ... But when you use it in the DbContext via the DbSet<Cateogry> type it becomes a table definition. Category是一个数据Model ,就其本身而言,它只是另一个代表某些东西的 class ...但是当您通过DbSet<Cateogry>类型在DbContext中使用它时,它就变成了一个表定义。 When you read this line:当您阅读此行时:

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

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

So far so good,到目前为止,一切都很好,

This next bit is related to a concept called Dependency Injection .下一点与称为依赖注入的概念有关。 the idea is that we can define at a global level a set of instructions that describe how to instantiate objects that we need to use a lot throughout the application without putting that instantiation logic everywhere.这个想法是我们可以在全局级别定义一组指令,这些指令描述如何实例化我们需要在整个应用程序中大量使用的对象,而无需将实例化逻辑放在任何地方。 It is a way to define this logic once and is inline with the DRY principal .这是一种定义此逻辑一次的方法,并且与DRY 主体内联。

  • You might think that the contructor of a class is an appropriate place for this type of information and before DI it was a common option, but for compex types this often requires a lot of external domain knowledge that is specific to the current application, which makes it hard to re-use your classes on other applications or contexts.您可能认为class的构造器是此类信息的合适位置,并且在 DI 之前这是一个常见的选项,但对于复杂类型,这通常需要大量特定于当前应用程序的外部领域知识,这使得很难在其他应用程序或上下文中重用您的类。 DI is an elegant solution to this that forces you to totally divorce the definition of your types and the implementation. DI 是一个优雅的解决方案,它迫使您完全脱离类型的定义和实现。

  • After contructors (and before DI), the next common implementation was to use the Factory Pattern to create objects using domain specific logic.在构造函数之后(以及在 DI 之前),下一个常见的实现是使用工厂模式使用特定领域的逻辑来创建对象。 Think of DI is a specific implementation of the Factory Pattern .认为 DI 是Factory Pattern特定实现。

So in Porgram.cs, the following code is registering the ApplicationDbContext type for DI, using the AddDbContext factory .因此在 Porgram.cs 中,以下代码使用AddDbContext工厂为 DI注册ApplicationDbContext类型。

builder.Services.AddDbContext<ApplicationDbContext>(options => 
options.UseSqlServer(
  builder.Configuration.GetConnectionString("DefaultConnection")
));
  • Part of this registration is to specify the connection string, in this case it is telling the underlying factory method to get the connection string from the configuration file.此注册的一部分是指定连接字符串,在这种情况下,它告诉底层工厂方法从配置文件中获取连接字符串。

The magic occurs now in the rest of your DI stack, in this case I think you have a repository called IndexModel , you might find later in the Program.cs there is more DI registration related to that class, but the idea is that when the IndexModel is needed , DI will call the constructor on that class.魔法现在发生在您的 DI 堆栈的 rest 中,在这种情况下,我认为您有一个名为IndexModel存储库,稍后您可能会在 Program.cs 中发现更多与该 class 相关的 DI 注册,但想法是,当IndexModel必需的,DI 将调用 class 上的构造函数。

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

As it requires an instance of ApplicationDbContext and DI knows how to create an instance of that type, it uses the AddDbContext factory to create a new instance of ApplicationDbContext and pass it through as an argument to the IndexModel constructor.由于它需要ApplicationDbContext的实例并且 DI知道如何创建该类型的实例,因此它使用AddDbContext工厂创建ApplicationDbContext的新实例并将其作为参数传递给IndexModel构造函数。

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

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