前言
在 .Net Core 2.2 中 Microsoft.AspNetCore.App 默认内置了 EntityFramework Core 包, 所以在使用过程中, 我们无需再从 NuGet 仓库单独应用 EFCore 包; 本文并不打算深入的介绍 EFCore 的各种使用方式, 原理解析, 本文重点在于解决让初学者在 10 分钟内快速使用上 EFCore 的问题.
1. Code First 方式
EFCore 支持 Code First 方式, 这个特性允许开发人员基于业务实体模型创建数据库
1.1 首先创建一个 ASP.NET Core webApi 项目 Ron.MSSQL, 如下
1.2 创建业务实体模型文件夹 Models, 添加两个业务实体 Topic,Post
- public class Topic
- {
- public int Id { get; set; }
- public string Title { get; set; }
- public string Content { get; set; }
- public DateTime CreateTime { get; set; }
- public virtual ICollection<Post> Posts { get; set; }
- }
- public class Post
- {
- public int Id { get; set; }
- public int TopicId { get; set; }
- public string Content { get; set; }
- public DateTime CreateTime { get; set; }
- public virtual Topic Topic { get; set; }
- }
上面定义的两个实体对象之间通过 Topic.Posts 和 Post.Topic 属性建立了主外键关系, 这两个表的主键为 Id, 且类型为 int , 这表示在下面的创建数据库过程中, EFCore 会自动的为这两个实体对象建立关系和主键, 并会自动设置 Id 字段为主键标识
1.3 编写数据库上下文对象, 该对象必须继承自 DbContext
DbContext 内置了很多个构造函数, 这里使用配置选项的方式, 实现方式也非常简单, 最终, 在 ForumContext 类中定义上面的实体业务模型集合即可
- public class ForumContext : DbContext
- {
- public ForumContext(DbContextOptions<ForumContext> options) : base(options)
- {
- }
- public DbSet<Topic> Topics { get; set; }
- public DbSet<Post> Posts { get; set; }
- }
1.4 在 appsettings.JSON 文件中配置数据库连接字符串, 这里使用的是本机安装的 SQLExpress, 指定数据库名称为: Forum
- "ConnectionStrings": {
- "Forum": "server=.\\SQLEXPRESS;uid=sa;pwd=123456;database=Forum;"
- }
1.5 在 Startup.cs 中配置连接字符串, 注入上下文对象
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddDbContext<ForumContext>(options =>
- {
- var connectionString = this.Configuration["ConnectionStrings:Forum"];
- options.UseSqlServer(connectionString);
- });
- ...
- }
上面的代码使用 AddDbContext 方法, 并配置了数据库连接字符串为配置文件中的 "ConnectionStrings:Forum" 节点的值
1.5 在项目的包管理器控制台中使用命令根据实体业务模型创建数据库
现在, 打开项目中的包管理器控制台
在控制台中输入以下两组命令
- Add-Migration Forum_v1
- Update-Database
在输入命令 Add-Migration Forum_v1 后, 回车, 控制台输出 To undo this action, use Remove-Migration. 表示命令执行成功; 同时可以看到, 在项目中多了一个文件夹 Migrations;
注意: 此时, 数据库 Forum 并没有被创建
在 Migrations 文件夹中; 当执行 Update-Database 命令后, EFCore 设计工具将根据 Migrations 中的定义去创建数据库, 最终, 控制台输出 Done 表示创建完成
查看数据库
从上图中可以看到, 数据库创建成功, 同时, Forum 数据库中还多了一个表 __EFMigrationsHistory , 该表存储的正是我们项目中的 Migrations 的内容, 只有两个字段, 对应 20190109031435_Forum_v1.cs 和 当前使用的 EFCore 版本号
如果后续有增加实体, 只需要再次执行 Add-Migration 命令即可
如果希望获得帮助, 还可在包管理器控制台执行命令 get-help Add-Migration
1.6 在项目中执行 CURD 操作
至此, 数据库创建完成, 为了在控制器中使用 ForumContext 对象, 我们在 HomeController 中使用依赖注入的方式获得 FormContext 对象, 以备后续使用
- private ForumContext context;
- public HomeController(ForumContext context)
- {
- this.context = context;
- }
现在, 尝试着在项目中执行一些增删改查的工作, 插入一条 Topic 记录, 在 HomeController 中编写以下代码
- [Route("api/[controller]"), ApiController]
- public class HomeController : ControllerBase
- {
- private ForumContext context;
- public HomeController(ForumContext context)
- {
- this.context = context;
- }
- [HttpGet]
- public ActionResult<IEnumerable<Topic>> Get()
- {
- var topics = context.Topics.ToList();
- return topics;
- }
- [HttpPost]
- public void Post([FromBody] TopicViewModel model)
- {
- context.Topics.Add(new Topic()
- {
- Content = model.Content,
- CreateTime = DateTime.Now,
- Title = model.Title
- });
- context.SaveChanges();
- }
- [HttpPut]
- public void Put([FromBody] TopicViewModel model)
- {
- var topic = context.Topics.Where(f => f.Id == model.Id).FirstOrDefault();
- topic.Title = model.Title;
- topic.Content = model.Content;
- context.Topics.Update(topic);
- context.SaveChanges();
- }
- [HttpDelete("{id}")]
- public void Delete(int id)
- {
- var topic = context.Topics.Where(f => f.Id == id).FirstOrDefault();
- context.Topics.Remove(topic);
- context.SaveChanges();
- }
- }
上面的代码定义了 Get/Post/Put/Delete 接口, 这是一个标准的 Resetful API , 通过依次调用模拟对数据库的 CURD 操作
2. DB First 的使用方式
在很多时候, 我们的开发方式是先设计好数据库模型, 然后再生成实体对象, 这种方式对于从其它语言迁移到 .Net Core 上非常友好, 从现有数据库中生成实体对象非常简单, 只需要一个命令即可, 还是以上面创建好的数据库 Forum 为例子
2.1 基于现有数据库生成实体对象, 在项目中的包管理器控制台输入命令, 指定使用的是 Microsoft.EntityFrameworkCore.SqlServer 驱动, 生成的实体模型输出到目录 DbModels 中
`Scaffold-DbContext "server=.\SQLEXPRESS;uid=sa;pwd=123456;database=Forum" Microsoft.EntityFrameworkCore.SqlServer -OutPutDir DbModels
2.2 执行结果
如果仅需要生成部分数据表, 还可以通过将 -Tables 参数添加到上述命令来指定要为哪些表生成实体. 例如 -Tables Blog,Post. 多个数据表以逗号分隔
2.3 项目中生成的实体对象文件夹
通过查看生成的代码比较, 和 Code First 方式基本相同, 使用方式完全一致
3. 导航属性
不管是 Code First 还是 DB First , 在实体对象中, 我们都可以看到有个一个导航属性, 比如 Topic.Posts 和 Post.Topic , 该导航属性定义了前缀 virtual 表示延迟加载此关联对象, 在 Code First 中, 导航属性还起到主外键关系定义的作用
结束语
本文介绍两种使用 EF Core 的方式
通过一个简单的 Forum 示例来一步一步的了解了 EFCore 的使用过程
示例代码下载
https://files.cnblogs.com/files/viter/Ron.MSSQL.zip
来源: https://www.cnblogs.com/viter/p/10243577.html