ASP.NET Core - DBContext

Entity 实体框架使您能够使用称为实体的公共语言运行时 (CLR) 对象来查询、插入、更新和删除数据。 实体框架将模型中定义的实体和关系映射到数据库。 它还提供 −

  • 将从数据库返回的数据具体化为实体对象。

  • 跟踪对对象所做的更改。

  • 处理并发。

  • 将对象更改传播回数据库。

  • 将对象绑定到控件。

负责将数据作为对象进行交互的主要类是 DbContext。 使用上下文的推荐方法是定义一个派生自 DbContext 的类,并公开表示上下文中指定实体集合的 DbSet 属性。

DBContext

从逻辑上讲,DBContext 映射到具有 DBContext 理解的架构的特定数据库。 在该 DBContext 类上,您可以创建类型为 DbSet<T> 的属性。 通用类型参数 T 将是一种实体类型,例如 Employee 是 FirstAppDemo 应用程序中的实体。


示例

让我们举一个简单的例子,其中我们将创建一个 DbContext 类。 在这里,我们需要在 Models 文件夹中添加一个新类并将其命名为 FirstAppDempDbContext。尽管这个类本身不是模型,但它确实将我们所有的模型放在一起,以便我们可以将它们与数据库一起使用。

FirstAppDemo Context

从 Microsoft.Data.Entity 命名空间中的 DbContext 类继承上下文类。 不在该类上实现 Employee 的 DbSet。

每个 DbSet 将映射到数据库中的一个表。 如果您有一个 employee 属性 DbSet,并且该属性的名称是 Employees,实体框架将默认在您的数据库中查找 Employees 表。

using FirstAppDemo.Models; 
using Microsoft.Data.Entity; 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks;  

namespace OdeToFood.Models { 
   public class FirstAppDemoDbContext : DbContext { 
      public DbSet<Employee> Employees { get; set; } 
   } 
} 

实现非常简单,因为我们只有一个模型可以使用。 我们只需要一个属性,即 Employee 的 DbSet,我们可以将此属性命名为 Employees

现在让我们将此类直接插入到控制器中,然后控制器可以使用 FirstAppDemoDbContext 查询数据库。我们将通过向 HomeController 类添加一个新类来简化所有这些,我们在其中实现添加员工和获取员工的方法,如以下程序所示。

using Microsoft.AspNet.Mvc; 

using FirstAppDemo.ViewModels; 
using FirstAppDemo.Services; 
using FirstAppDemo.Entities; 
using FirstAppDemo.Models; 

using System.Collections.Generic; 
using System.Linq;  

namespace FirstAppDemo.Controllers { 
   public class HomeController : Controller { 
      public ViewResult Index() { 
         var model = new HomePageViewModel(); 
         
         using (var context = new FirstAppDemoDbContext()) { 
            SQLEmployeeData sqlData = new SQLEmployeeData(context); 
               model.Employees = sqlData.GetAll(); 
         }  
         return View(model); 
      } 
   }  
   public class SQLEmployeeData { 
      private FirstAppDemoDbContext _context { get; set; } 
      public SQLEmployeeData(FirstAppDemoDbContext context) { 
         _context = context;
      } 
      public void Add(Employee emp) { 
         _context.Add(emp); 
         _context.SaveChanges(); 
      } 
      public Employee Get(int ID) { 
         return _context.Employees.FirstOrDefault(e => e.Id == ID); 
      } 
      public IEnumerable<Employee> GetAll() { 
         return _context.Employees.ToList<Employee>(); 
      } 
   } 
   public class HomePageViewModel { 
      public IEnumerable<Employee> Employees { get; set; } 
   } 
}   

在上面的 SQLEmployeeData 类中,您可以看到我们已经定义了 Add 方法,该方法将向上下文添加一个新的员工对象,然后保存更改。 在 Get 方法中,它将根据 ID 返回一个员工。 而在 GetAll 方法中,它将返回数据库中所有员工的列表。


配置 Entity 实体框架服务

要有一个可用的 Entity 实体框架 DBContext,我们需要更改应用程序的配置。 我们将需要添加一个连接字符串,以便我们的 DBContext 知道要转到哪个服务器以及要查询哪个数据库。

  • 我们会将连接字符串放入 JSON 配置文件中。

  • 我们还需要在 Startup 类的 ConfigureServices 方法中添加一些服务。

  • 实体框架,就像 ASP.NET 和 MVC 框架一样,实体框架依赖于依赖注入,为了注入工作,运行时需要知道实体框架使用的各种服务。

  • 有一个简单的配置 API,可以添加我们需要的所有默认服务。

让我们转到 AppSettings.json 文件并添加连接字符串,如以下程序所示。

{ 
   "message": "Hello, World! this message is from configuration file...", 
   "database": { 
      "connection": "Data Source=(localdb)\\mssqllocaldb;Initial Catalog=FirstAppDemo" 
   } 
}

现在让我们转到 Startup 类,我们需要在其中添加一些额外的服务以使实体框架正常工作。 具体而言,我们需要做三件与实体框架相关的事情 −

  • 我们需要添加 core Entity 实体框架服务。

  • 我们还需要添加 SQL Server 相关的实体框架服务。

  • 我们需要告诉实体框架我们的 DBContext。

所有这些都可以通过可用作 IServiceCollection 上的扩展方法的方法来完成,如以下程序所示。

public void ConfigureServices(IServiceCollection services) { 
   services.AddMvc(); 
   services.AddEntityFramework() 
      .AddSqlServer() 
      .AddDbContext<FirstAppDemoDbContext>
   
   (option => option.UseSqlServer(Configuration["database:connection"])); 
} 
  • 第一个方法是AddEntityFramework。 这将添加 core Entity 实体框架服务,即默认服务。

  • 但是由于 Entity 实体框架现在设计用于处理不同类型的数据库,包括非关系数据库,我们需要进行第二次调用以告知 Entity 实体框架添加其默认的 SQL Server 相关服务。

  • 然后我们还需要将我的 DBContext 类告诉实体框架,以便它可以适当地构造该类的实例,我们可以通过第三种方法来实现,即 AddDbContext 方法。

  • 这一个采用通用类型参数,我们在其中指定 DBContext 派生类的类型,FirstAppDemoDbContext

  • 在 AddDbContext 中,我们需要描述 DBContext 的选项。

  • 这可以通过lambda 表达式 来完成; 这是我们接收选项参数并且实体框架可以支持不同数据库的操作。我们需要做的就是告诉实体框架这个特定的 DBContext 将要使用 UseSqlServer

  • 此方法需要一个参数,即要使用的 connectionString

以下是 Startup.cs 文件的完整实现。

using Microsoft.AspNet.Mvc; 

using FirstAppDemo.ViewModels; 
using FirstAppDemo.Services; 
using FirstAppDemo.Entities; 
using FirstAppDemo.Models; 

using System.Collections.Generic; 
using System.Linq;  

namespace FirstAppDemo.Controllers { 
   public class HomeController : Controller { 
      public ViewResult Index() { 
         var employee = new Employee { Id = 1, Name = "Mark Upston1" }; 
         using (var context = new 
         
         FirstAppDemoDbContext()) { 
            SQLEmployeeData sqlData = new SQLEmployeeData(context); 
            sqlData.Add(employee); 
         } 
         
         //var employee = new Employee { ID = 1, Name = "Mark Upston" }; 
         return View(employee); 
      } 
   }  
   public class SQLEmployeeData { 
      private FirstAppDemoDbContext _context { get; set; }  
      public SQLEmployeeData(FirstAppDemoDbContext context) { 
         _context = context; 
      }  
      public void Add(Employee emp) { 
         _context.Add(emp); 
         _context.SaveChanges(); 
      } 
      public Employee Get(int ID) { 
         return _context.Employees.FirstOrDefault(e => e.Id == ID); 
      } 
      public IEnumerable<Employee> GetAll() { 
         return _context.Employees.ToList<Employee>(); 
      } 
   } 
} 

现在我们需要设置数据库。 建立数据库的一种方法是使用实体框架创建数据库,这需要两步过程 −


第一步

这涉及以下内容 −

  • 向我们的项目添加迁移代码。

  • 迁移代码为C# 代码。 可以执行此操作以在数据库模式中创建数据库。

  • 实体框架可以为我们生成这个迁移代码。

  • 实体框架查看数据库和我们的模型,并找出使应用程序工作所需的模式更改。

  • 因此,当我们添加额外的模型或对现有模型(如 Employee 类)进行更改时,可以继续向我们的项目添加迁移并保持数据库模式同步。


第二步

这涉及以下内容 −

  • 在这里,我们需要显式应用这些迁移来更新数据库。

  • 这两项任务都可以通过从控制台窗口使用一些简单的命令来完成。

  • 我们制作了project.json。

  • 这就是我们在 project.json 中添加命令的原因,其中"ef"映射到 EntityFramework.Commands。

让我们打开 Visual Studio 的开发人员命令提示符来运行我们需要添加迁移和应用迁移的命令。 最简单的方法是转到应用程序根目录。

开发人员命令提示符

如果您位于包含 project.json 文件的文件夹中,那么您位于正确的文件夹中。 在这里,需要执行一个名为 dnvm 的命令。 这是 .NET 版本管理器,它将告诉系统我们要使用的运行时。

现在让我们使用以下命令。

dnvm list 

当您按 Enter 时,您将看到以下输出。

命令提示符中的输出

我们需要告诉 dnvm 我们想要使用特定的 runtimes。这将使我们能够访问我们想要执行的 dotnet 命令或 dnx 命令。

执行以下命令。

dnvm use1.0.0-rc1-update1 -p

按 Enter 键。

DNVM

dnvm 将设置我们的路径和环境变量以包含一个 bin 目录,该目录将使我们能够访问此 dnx 实用程序。 让我们执行 dnx ef 命令。

DNX EF 命令

这是 .NET 执行环境,使用 dnx,我们可以调用我们在 project.json 文件中列出的命令。 执行这些命令通常非常容易。 当您键入 dnx ef 时,您将看到一个帮助屏幕。 您不必记住所有选项。 您可以从 Entity Framework Commands 中看到可用的命令,共有三个。

首先,我们需要添加迁移来执行下面的命令。

dnx ef migrations add v1

按 Enter 键。

DNX EF Migrations

实体框架将找到该上下文并查看其中的模型。 它将知道之前没有迁移,因此它将生成第一个迁移。 这里,v1 是数据库的版本 1。 它将在解决方案资源管理器中创建一个新文件夹并生成代码。

Entity 实体框架

迁移本质上是一个 C# 代码,用于生成 SQL 命令以修改 SQL 数据库中的架构。

using System; 
using System.Collections.Generic; 

using Microsoft.Data.Entity.Migrations; 
using Microsoft.Data.Entity.Metadata;  

namespace FirstAppDemo.Migrations { 
   public partial class v1 : Migration { 
      protected override void Up(MigrationBuilder migrationBuilder) { 
         
         migrationBuilder.CreateTable(name: "Employee", columns: table => new { 
            Id = table.Column<int>(nullable: false)    
               .Annotation("SqlServer:ValueGenerationStrategy",
               SqlServerValueGenerationStrategy.IdentityColumn),                        
               Name = table.Column<string>(nullable: true) 
         }, 
         constraints: table => { 
            table.PrimaryKey("PK_Employee", x => x.Id); 
         }); 
      }  
      protected override void Down(MigrationBuilder migrationBuilder) { 
         migrationBuilder.DropTable("Employee"); 
      } 
   } 
}

您可以看到它将创建一个名为 Employees 的表。

  • 这个表应该有两列——一个 ID 和一个 Name 列。

  • 按照惯例,当实体框架发现您有一个名为 Id 的属性时,它将使该属性成为数据库中的主键,或者更确切地说,使该列成为数据库中的主键。

  • 在这里,我们将使用 SQL Server。 默认情况下,实体框架将使它成为一个 IdentityColumn,这意味着 SQL Server 将为我们生成 ID。

让我们通过键入"dnx ef database update"命令将这些 ID 应用于数据库。

DNX EF Database Update

可以看到命令应用了迁移。

现在让我们转到 SQL Server 对象资源管理器,并刷新数据库,您现在可以看到我们有一个 FirstAppDemo 数据库。

SQL Server 对象资源管理器

您还可以查看我们的 Employee 表,我们甚至可以查看该表中 ID 列为主键的列。

让我们右键单击 dbo.Employee 表并选择"查看数据"。

DBO Employee

在我们运行应用程序之前,让我们添加一些数据。 当我们启动应用程序时,我们应该从数据库中看到一些数据。

让我们在这里添加几行数据。

几行数据

现在让我们更新 index.cshtml 文件。 它以表格形式显示所有数据。

@model FirstAppDemo.Controllers.HomePageViewModel 
<html xmlns="http://www.w3.org/1999/xhtml"> 
   <head> 
       <title>Home</title> 
   </head> 

   <body> 
      <h1>Welcome!</h1> 
      
      <table> 
         @foreach (var employee in Model.Employees) { 
            <tr> 
               <td>   
                  @Html.ActionLink(employee.Id.ToString(), "Details", new 
                     { id = employee.Id }) 
               </td> 
               <td>@employee.Name</td> 
            </tr> 
         } 
      </table> 
   </body> 
</html>

运行应用程序后,它应该会产生以下输出。

最终输出