EF Core 在实际开发中,如何分层?

简介: EF Core 在实际开发中,如何分层?

前言:什么是分层?

  1. 分层就是将 EF Core 放在单独的项目中,其它项目如 Asp.net core webapi 项目引用它
  2. 这样的好处是解耦和项目职责的清晰划分,并且可以重用 EF Core 项目
  3. 但是也会数据库迁移变得复杂起来

Step by step 步骤

  1. 创建一个 .NET 类库项目,项目名字为 BooksEFCore
  2. 引用以下 Nuget 包

Microsoft.EntityFrameworkCore.Relational

Microsoft.EntityFrameworkCore.SqlServer

Microsoft.EntityFrameworkCore.Tools

3.创建实体类 Book

// 把Book类声明为一个记录类,而不是普通的类,主要是为了让编译器自动生成ToString方法,简化对象的输出
public record Book
{
  public Guid Id { get; set; }
  public string Name { get; set; }
  public double Price { get; set; }
}

4.配置实体类

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
class BookConfig : IEntityTypeConfiguration<Book>
{
  public void Configure(EntityTypeBuilder<Book> builder)
  {
    builder.ToTable("T_Books2");
  }
}

5.创建上下文类【注意,这里有跟单体 EF Core 项目不一样的地方,看注释

using Microsoft.EntityFrameworkCore;
public class MyDbContext:DbContext
{
  public DbSet<Book> Books { get; set; }
  //注意:
  //在运行时通过读取配置来确定要连接的数据库
  //不再重写 OnConfiguring 方法和在其中调用 UseSqlServer 等方法来设置要使用的数据库
  //为 MyDbContext 类增加了 DbContextOptions<MyDbContext> 类型参数的构造方法
  //DbContextOptions 是一个数据库连接配置对象,在 ASP.NET Core 项目中提供对 DbContextOptions 的配置
  public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
  {
  }
  
  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
    base.OnModelCreating(modelBuilder);
    modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
  }
}

6.创建一个 Asp.net core webapi 项目,命名为 “EFCore测试用WebAPI项目1”

7.引用 EF Core 类项目 BooksEFCore

9.打开 appsettings.json 文件并添加数据库连接字符串配置

{
  "Logging": {
  "LogLevel": {
    "Default": "Information",
    "Microsoft.AspNetCore": "Warning"
  }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
  "Default": "Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

10.打开 Program.cs 文件,注册数据库上下文服务

using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 注册数据库上下文服务
// 使用AddDbContext方法来通过依赖注入的方式让MyDbContext采用指定的连接字符串连接数据库。
// 由于AddDbContext方法是泛型的,因此可以为同一个项目中的多个不同的上下文设定连接不同的数据库。
builder.Services.AddDbContext<MyDbContext>(opt =>
{
  string connStr = builder.Configuration.GetConnectionString("Default")!;
  opt.UseSqlServer(connStr);
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
  app.UseSwagger();
  app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

11.创建 TestController 控制器,编写数据库读写的测试代码

using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("[controller]/[action]")]
public class TestController : ControllerBase
{
  private readonly MyDbContext dbCtx;
  /// <summary>
  /// 用依赖注入的形式来创建上下文
  /// </summary>
  /// <param name="dbCtx"></param>
  public TestController(MyDbContext dbCtx)
  {
    this.dbCtx = dbCtx;
  }
  [HttpPost]
  public async Task<long> Save()
  {
    dbCtx.Add(new Book { Id = Guid.NewGuid(), Name = "零基础趣学C语言", Price = 59 });
    await dbCtx.SaveChangesAsync();
    return dbCtx.Books.LongCount();
  }
}

11.生成实体类的迁移脚本

  1. 回到 EF Core 类项目 BooksEFCore

2.新建一个实现 IDesignTimeDbContextFactory 接口的类 MyDesignTimeDbContextFactory

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
//在多项目的环境下执行 EF Core 的数据库迁移有很多特殊的要求
//容易出错,因为数据库连接在其它项目中
//可以通过 IDesignTimeDbContextFactory 接口来解决这个问题
//当项目中存在一个 IDesignTimeDbContextFactory 接口的实现类的时候,
//数据库迁移工具就会调用这个实现类的 CreateDbContext 方法来获取上下文对象,
//然后迁移工具会使用这个上下文对象来连接数据库
//此代码只用于开发环境
//生产环境可以去掉此代码
class MyDesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
{
  public MyDbContext CreateDbContext(string[] args)
  {
    DbContextOptionsBuilder<MyDbContext> builder = new();
    string connStr = "Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=true";
    //也可以从环境变量或者其它配置文件中读取,如下:
    //string connStr = Environment.GetEnvironmentVariable("ConnectionStrings:BooksEFCore");
    builder.UseSqlServer(connStr);
    return new MyDbContext(builder.Options);
  }
}

3.设置 BooksEFCore 为启动项目

4.打开 菜单-工具-Nuget包管理-程序包管理器控制台,并选中 BooksEFCore

5.执行 Add-Migration Init 命令生成数据库迁移脚本

6.然后执行 Update-database 命令即可完成数据库的创建


相关文章
|
SQL 存储 关系型数据库
一个库帮你快速实现EF Core数据仓储模式
一个库帮你快速实现EF Core数据仓储模式
253 1
|
Linux 测试技术 数据库
7步教你搞定Linux禅道系统安装
7步教你搞定Linux禅道系统安装
569 0
|
数据安全/隐私保护 Docker 容器
ElasticStack----使用Docker方式安装单节点的8.1.3版本的ElasticSearch
ElasticStack----使用Docker方式安装单节点的8.1.3版本的ElasticSearch
1963 0
ElasticStack----使用Docker方式安装单节点的8.1.3版本的ElasticSearch
|
API
.net core工具组件系列之Autofac—— 第二篇:Autofac的3种依赖注入方式(构造函数注入、属性注入和方法注入),以及在过滤器里面实现依赖注入
本篇文章接前一篇,建议可以先看前篇文章,再看本文,会有更好的效果。前一篇跳转链接:https://www.cnblogs.com/weskynet/p/15046999.html
1225 0
.net core工具组件系列之Autofac—— 第二篇:Autofac的3种依赖注入方式(构造函数注入、属性注入和方法注入),以及在过滤器里面实现依赖注入
|
机器学习/深度学习 人工智能 算法
AI在体育分析与预测中的深度应用:变革体育界的智能力量
AI在体育分析与预测中的深度应用:变革体育界的智能力量
1314 31
|
存储 数据库 开发者
深入浅出讲解Entity Framework Core中的复杂类型与值对象:从理论到实践的全方位指南,附带详实代码示例与最佳应用技巧
【8月更文挑战第31天】本文通过教程形式详细介绍了如何在 Entity Framework Core 中使用复杂类型与值对象,帮助开发者更自然地映射实体和数据库间的关系。文章首先指导创建基于 EF Core 的项目,并添加相关 NuGet 包。接着,通过具体代码示例展示了如何配置数据库上下文、定义领域模型,并使用复杂类型与值对象进行数据存储和查询。最后总结了使用这些技术的优势,包括简化复杂数据结构映射、提高可维护性及数据一致性。
346 0
|
存储 Java 编译器
方法区、永久代、元空间之间有什么关系
方法区、永久代、元空间之间有什么关系
|
Linux Windows
【已解决】Error: error:0308010C:digital envelope routines::unsupported
【已解决】Error: error:0308010C:digital envelope routines::unsupported
1156 0
|
搜索推荐 数据可视化 5G
从《三体》中的“降维打击”看网络世界,论维度升级的方法与实践
刘慈欣的《三体》为人们拉开一副天马行空的科幻画卷。在地球人类文明和三体文明的信息交流、生死搏杀历程中,“黑暗森林”推动星球文明间的关系发展,也通过一个毁灭性武器--二向箔,“降维打击”终结了人类文明。 在商业的暗黑森林中,无论是商业帝国还是创业公司,都面临着被“降维打击”的潜在风险,而防御风险的最高效模式,是通过维度的增值来引导发展,真正实现“发展+转型”,在业务主航道上拓展出新的领域。随着新领域,新方向、新业务的不断拓展,企业底层的ICT核心架构也需要随之升级增维,此时企业们该如何抓住破局关键呢?
|
SQL 监控 关系型数据库
【MySQL】如何阅读死锁日志
一 前言    工欲善其事必先利其器,前面分析了很多死锁案例,并没有详细的介绍如何通过死锁日志来诊断死锁的成因。本文将介绍如何读懂死锁日志,尽可能的获取信息来辅助我们解决死锁问题。
5450 153