📜  ASP.NET Core-DBContext

📅  最后修改于: 2020-11-21 04:59:04             🧑  作者: Mango


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

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

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

  • 处理并发。

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

  • 将对象绑定到控件。

负责与数据作为对象进行交互的主要类是DbContext。建议使用上下文的方法是定义一个类,该类派生自DbContext并暴露DbSet属性,这些属性表示上下文中指定实体的集合。

数据库上下文

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

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

FirstAppDemo上下文

从Miscrosoft.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 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 GetAll() { 
         return _context.Employees.ToList(); 
      } 
   } 
   public class HomePageViewModel { 
      public IEnumerable Employees { get; set; } 
   } 
}   

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

配置实体框架服务

要拥有可用的Entity Framework 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类,在这里我们需要添加一些其他服务以使Entity Framework正常工作。具体来说,我们需要做的三件事与实体框架有关-

  • 我们需要添加核心的实体框架服务。

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

  • 我们需要向实体框架介绍我们的DBContext。

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

public void ConfigureServices(IServiceCollection services) { 
   services.AddMvc(); 
   services.AddEntityFramework() 
      .AddSqlServer() 
      .AddDbContext
   
   (option => option.UseSqlServer(Configuration["database:connection"])); 
} 
  • 第一种方法是AddEntityFramework 。这将添加核心Entity Framework服务,默认服务。

  • 但是,由于现在已将实体框架设计为与不同类型的数据库(包括非关系数据库)一起使用,因此我们需要进行第二次调用以告知实体框架添加其默认的SQL Server相关服务。

  • 然后,我们还需要告知Entity Framework我的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 GetAll() { 
         return _context.Employees.ToList(); 
      } 
   } 
} 

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

第一步

这涉及以下内容-

  • 将迁移代码添加到我们的项目中。

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

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

  • 实体框架着眼于数据库和我们的模型,并指出了使应用程序正常工作需要进行哪些模式更改。

  • 因此,当我们添加其他模型或对现有模型(例如Employee类)进行更改时,我们可以继续向项目中添加迁移,并使数据库架构保持同步。

第二步

这涉及以下内容-

  • 在这里,我们需要明确地应用那些迁移来更新数据库。

  • 通过在控制台窗口中使用一些简单的命令,即可完成这两项任务。

  • 我们已经制作了project.json。

  • 这就是为什么我们要在project.json中添加一个命令,其中“ ef”映射到EntityFramework.Commands。

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

开发人员命令提示

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

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

dnvm list 

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

在命令提示符中输出

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

执行以下命令。

dnvm use1.0.0-rc1-update1 -p

按Enter键。

DNVM

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

DNX EF命令

这是使用dnx的.NET执行环境,我们可以调用在project.json文件中列出的命令。通常,执行这些命令非常容易。键入dnx ef时,将显示帮助屏幕。您不必记住所有选项。您可以从“实体框架命令”中看到可用的命令,其中有三个。

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

dnx ef migrations add v1

按Enter键。

DNX EF迁移

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

实体框架

迁移实质上是一种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(nullable: false)    
               .Annotation("SqlServer:ValueGenerationStrategy",
               SqlServerValueGenerationStrategy.IdentityColumn),                        
               Name = table.Column(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数据库更新

您可以看到该命令已应用迁移。

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

SQL Server对象浏览

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

让我们右键单击dbo.Employee表,然后选择“查看数据”。

DBO员工

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

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

几行数据

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

@model FirstAppDemo.Controllers.HomePageViewModel 
 
    
       Home 
    

    
      

Welcome!

@foreach (var employee in Model.Employees) { }
@Html.ActionLink(employee.Id.ToString(), "Details", new { id = employee.Id }) @employee.Name

一旦运行该应用程序,它将产生以下输出。

最终输出