目录
介绍
背景
使用代码
创建项目
更改Razor视图
添加数据模型
向应用程序添加数据
安装实体框架核心包
定义连接字符串
创建数据库上下文类
配置实体框架核心
创建存储库
创建数据库迁移
创建种子数据
显示书籍列表
准备控制器
更新视图
运行应用程序
兴趣点
介绍要从这些文章中获得最大收益,您应该熟悉Web开发的基础知识,了解HTML、CSS和JavaScript的工作原理,了解C#、什么是MVC模型,并且还应该了解一些基础知识.NET Core、ASP.NET Core和Entity Framework Core。如果您还没有做过这些,您可以从W3schools或Microsoft docs开始使用它们。
在这些文章中,通过一个名为BooksStore的项目,我想向您展示一个从开始到部署的真实开发过程。我使用了Windows 10、Visual Studio 2019和SQL Server LocalDB。
背景在我的应用程序中BooksStore,我将创建一个客户可以按类型和页面浏览的在线图书目录,一个用户可以添加和删除图书的购物车,以及一个客户可以输入他们的运输详细信息的结帐。我还将创建一个管理区域,其中包括用于管理目录的创建、读取、更新和删除(CRUD)工具,并且我将保护它,以便只有登录的管理员才能进行更改。
使用代码 创建项目在Visual Studio中,选择Create a new project,选择ASP.NET Core Web Application和Next:
为项目命名BooksStore并选择Create:
选择Web应用程序(模型-视图-控制器),然后选择创建:
请注意,我选择了ASP.NET Core 3.1——Visual Studio 2019中的长期支持。
更改Razor视图Razor视图引擎负责处理扩展名为.cshtml的视图文件以生成HTML响应。将Views/Shared/_Layout.cshtml文件的内容替换为以下标记:
BooksStore
@RenderBody()
并且还将Views/Home /Index.cshtml文件的内容替换为以下标记:
Welcome to BooksStore
由于这是一个电子商务应用程序,我需要的最明显的模型是一本书。在Models文件夹中添加一个名为Book.cs的类文件,并将该文件的默认内容替换为以下代码:
using System.ComponentModel.DataAnnotations.Schema;
namespace BooksStore.Models {
public class Book {
public long BookID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
[Column(TypeName = "decimal(8, 2)")]
public decimal Price { get; set; }
public string Genre { get; set; }
}
}
现在,在继续之前,我们可以运行应用程序以确保它按预期构建和运行:
该BooksStore应用程序将其数据存储在SQL Server LocalDB数据库中,该数据库使用Entity Framework Core(EF Core)进行访问。因此,第一步是通过选择工具菜单,选择NuGet包管理器>包管理器控制台(PMC)将EF Core添加到项目中。在PMC中,运行以下命令:
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 3.1.1
配置设置(例如数据库连接字符串)存储在JSON配置文件中。将连接字符串添加到appsettings.json文件:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"BooksStoreConnection": "Server=(localdb)\\MSSQLLocalDB;
Database=BooksStore;MultipleActiveResultSets=true"
}
}
此配置字符串指定一个名为BooksStore的LocalDB数据库并启用多活动结果集功能(MARS),这是BooksStore应用程序使用Entity Framework Core进行的一些数据库查询所必需的。
创建数据库上下文类Entity Framework Core通过上下文类提供对数据库的访问。将一个名为BooksStoreDbContext.cs的类文件添加到Models文件夹,并使用它来定义具有以下代码的类:
using Microsoft.EntityFrameworkCore;
namespace BooksStore.Models {
public class BooksStoreDbContext: DbContext {
public BooksStoreDbContext (DbContextOptions< BooksStoreDbContext > options)
: base(options) { }
public DbSet Books { get; set; }
}
}
DbContext基类提供对Entity Framework Core底层功能的访问,而Books属性将提供Book对数据库中对象的访问。该类BooksStoreDbContext派生自DbContext并添加了将用于读取和写入应用程序数据的属性。
配置实体框架核心必须配置Entity Framework Core,以便它知道它将连接到的数据库的类型,哪个连接字符串描述该连接,以及哪个上下文类将在数据库中呈现数据。为此,我们对Startup.cs文件进行一些更改:
using BooksStore.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
...
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext(opts => {
opts.UseSqlServer(
Configuration["ConnectionStrings:BooksStoreConnection"]);
});
}
...
Entity Framework Core配置AddDbContext方法,注册数据库上下文类,配置与数据库的关系。
该UseSQLServer方法声明正在使用SQL Server,并通过IConfiguration对象读取连接字符串。
创建存储库下一步是创建存储库接口和实现类。存储库模式是使用最广泛的模式之一,它提供了一种一致的方式来访问数据库上下文类提供的功能。
在Models文件夹中添加一个名为IBooksStoreRepository.cs的类文件,并使用它来定义接口,代码如下:
using System.Linq;
namespace BooksStore.Models {
public interface IBooksStoreRepository {
IQueryable Books { get; }
}
}
此接口使用IQueryable允许调用者获取Book对象序列。
要创建存储库接口的实现,请在Models文件夹中添加一个名为EFBooksStoreRepository.cs的类文件,并使用它来定义具有以下代码的类:
using System.Linq;
namespace BooksStore.Models {
public class EFBooksStoreRepository : IBooksStoreRepository {
private BooksStoreDbContext context;
public EFBooksStoreRepository (BooksStoreDbContext ctx) {
context = ctx;
}
public IQueryable Books => context.Books;
}
}
现在,我们将在Startup类中添加以下语句,为用作实现EFBooksStoreRepository类的IBooksStoreRepository接口创建服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext(opts => {
opts.UseSqlServer(
Configuration["ConnectionStrings:BooksStoreConnection"]);
});
services.AddScoped();
}
该AddScoped方法创建一个服务,其中每个HTTP请求都获取自己的存储库对象,这是Entity Framework Core通常使用的方式。
创建数据库迁移Entity Framework Core能够通过称为迁移的功能使用数据模型类为数据库生成架构。从“工具”菜单中,选择NuGet包管理器>包管理器控制台(PMC)。在PMC中,输入以下命令:
Install-Package Microsoft.EntityFrameworkCore.Tools -Version 3.1.1
Add-Migration InitialCreate
Update-Database
我们使用该Add-Migration命令创建数据库迁移并使用该Update-Database命令将其应用到数据库。我们还从nuget安装了Microsoft.EntityFrameworkCore.Tools软件包以使用这些命令。
创建种子数据为了填充数据库并提供一些示例数据,我在Models文件夹中添加了一个名为SeedData.cs的类文件,并使用以下代码定义了该类:
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
namespace BooksStore.Models
{
public static class SeedData
{
public static void EnsurePopulated(IApplicationBuilder app)
{
BooksStoreDbContext context = app.ApplicationServices.CreateScope().
ServiceProvider.GetRequiredService();
if (context.Database.GetPendingMigrations().Any())
{
context.Database.Migrate();
}
if (!context.Books.Any())
{
context.Books.AddRange(
new Book
{
Title = "Atomic Habits",
Description = "An Easy & Proven Way to Build Good Habits &
Break Bad Ones",
Genre = "Self-Help",
Price = 11.98m
},
new Book
{
Title = "How to Win Friends & Influence People",
Description = "You can go after the job you want...and get it!
You can take the job you have...and improve it!",
Genre = "Self-Help",
Price = 17.46m
},
new Book
{
Title = "Rich Dad Poor Dad",
Description = "What the Rich Teach Their Kids About Money
That the Poor and Middle Class Do Not!",
Genre = "Personal Finance",
Price = 13.41m
},
new Book
{
Title = "The Psychology of Money",
Description = "Doing well with money isn’t necessarily
about what you know. It’s about how you behave.
And behavior is hard to teach,
even to really smart people.",
Genre = "Money Management",
Price = 18.69m
},
new Book
{
Title = "48 Laws of Power",
Description = "Amoral, cunning, ruthless, and instructive,
this piercing work distills 3,000 years of the
history of power into 48 well-explicated laws.",
Genre = "Political Science",
Price = 31.26m
}
);
context.SaveChanges();
}
}
}
}
最后的更改是在应用程序启动时为数据库播种,我们通过使用以下代码EnsurePopulated从类中添加对方法的调用来完成此操作:Startup
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
SeedData.EnsurePopulated(app);
}
通过将默认内容替换为以下代码,在BooksStore/Controllers文件夹中的HomeController.cs 文件中准备控制器:
using Microsoft.AspNetCore.Mvc;
using BooksStore.Models;
namespace BooksStore.Controllers
{
public class HomeController : Controller
{
private IBooksStoreRepository repository;
public HomeController(IBooksStoreRepository repo)
{
repository = repo;
}
public IActionResult Index() => View(repository.Books);
}
}
这称为依赖注入,其方法允许HomeController对象通过IStoreRepository接口访问应用程序的存储库,而无需知道配置了哪个实现类。
更新视图使用以下标记更新SportsStore/Views/Home文件夹中的Index.cshtml文件的内容:
@model IQueryable
@foreach (var p in Model)
{
@p.Title
@p.Description
@p.Genre
@p.Price.ToString("c")
}
从上图中可以看到,Index.cshtml视图将数据库中的书籍显示在一个页面上。在下一篇文章中,我将添加对分页的支持,以便视图在一个页面上显示较少数量的产品,并且用户可以从一个页面移动到另一个页面以查看整体目录。
https://www.codeproject.com/Articles/5327033/An-Introduction-to-ASP-NET-Core-MVC-through-an-Exa