首页 > 其他分享 >EF Core 在实际开发中,如何分层?

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

时间:2024-01-24 17:34:31浏览次数:31  
标签:Core builder 数据库 EF Microsoft EntityFrameworkCore 分层 上下文 public

iamge

前言:什么是分层?

  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

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

    {
      "Logging": {
    	"LogLevel": {
    	  "Default": "Information",
    	  "Microsoft.AspNetCore": "Warning"
    	}
      },
      "AllowedHosts": "*",
      "ConnectionStrings": {
    	"Default": "Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=true"
      }
    }	
    
  9. 打开 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();	
    
  10. 创建 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 命令即可完成数据库的创建

扩展

  1. 在进行项目开发时,推荐采用 "小上下文" 策略
  2. "小上下文" 策略特点是:
    • 把关系紧密的实体类放到同一个上下文类中,把关系不紧密的实体类放到不同的上下文类中
    • 也就是项目中存在多个上下文类,每个上下文类中只有少数几个实体类
    • 有点 DDD 的味道
  3. "小上下文" 策略的好处:
    • 一个上下文实例初始化的时候,实体类的配置等过程将非常快,其不会成为性能瓶颈
    • 如果启用了数据库连接池,数据库连接的创建也不会成为性能瓶颈。

标签:Core,builder,数据库,EF,Microsoft,EntityFrameworkCore,分层,上下文,public
From: https://www.cnblogs.com/JackyGz/p/17985187

相关文章

  • git pull : 提示 can't lock ref 'xxxx' ,some local refs could not be update
    在执行gitpull操作时可能会遇到can'tlockref'xxxx',somelocalrefscouldnotbeupdate;tryrunninggitremotepruneorigintoremoveanyold,conflictingbranches。出现以上的问题的原因是本地所追踪的远程分支,与本地对应分支不同,导致的gitpull失败。如有一......
  • js/ts中Date类的ref响应式 -- VUE3
    现象:Date对象无法响应式原因:Date是个深层对象,外面那层可以响应,但是更改里面的层,则不会被侦测到改动解决:强制触发副作用即可参考文档:https://cn.vuejs.org/api/reactivity-advanced.html#triggerref<template><divclass="cnblogs_yucloud">{{DateTime}}</div>......
  • Adobe After Effects 2024:让你的创意动起来 mac/win版
    AdobeAfterEffects2024是一款专业的数字视觉效果、合成和运动图形软件,被广泛应用于电影、电视、广告和网络媒体等领域。它能够帮助用户快速高效地将创意转化为令人惊叹的视觉效果,是视觉艺术家的首选工具之一。→→↓↓载AdobeAfterEffects2024mac/win版在AdobeAfterE......
  • NetCore获取文件内容
    1、注入IWebHostEnvironmentprivateIWebHostEnvironment_hostEnvironment;publicFormBaseController(IWebHostEnvironmenthostEnvironment){_hostEnvironment=hostEnvironment;} 2、读取根目录下文件内容(Templates/Index.html)publicasyncTask<IActionRes......
  • EFCore 经验
    注意:EFCore在执行Remove-Migration取消最后一次迁移生成的文件时,先不要更改Config配置文件,否则可能无法执行取消操作当主表和明细表是主从关系时,默认生成时为级联删除,不需要在配置文件中声明publicclassProductionPlanDetailConfig:IEntityTypeConfiguration<Production......
  • 死磕Spring之IoC篇 - BeanDefinition 的解析过程(面向注解)
    BeanDefinition的解析过程(面向注解)前面的几篇文章对Spring解析XML文件生成BeanDefinition并注册的过程进行了较为详细的分析,这种定义Bean的方式是面向资源(XML)的方式。面向注解定义Bean的方式Spring的处理过程又是如何进行的?本文将会分析Spring是如何将 @Component......
  • 不能在此路径中使用此配置节。如果在父级别上锁定了该节,便会出现这种情况。锁定是默认
    今天运行项目的时候出现了这个错误....查了一下解决的方法。具体方案如下: 1、先确认安装IIS的时候有没有装Asp.Net,如果没安装的话,安装上即可。(XTHS:采用这步,就可以了!) 2、IIS采用了更安全的web.config管理机制,默认情况下会锁住配置项不允许更改。用超级管理员的身份执......
  • MapStruct+Maven+Lombok问题NoSuchBeanDefinitionException、does not have an access
    概述先直接说我遇到的问题吧,SpringBoot应用启动失败:ERROR|org.springframework.boot.web.embedded.tomcat.TomcatStarter|onStartup|61|-ErrorstartingTomcatcontext.Exception:org.springframework.beans.factory.UnsatisfiedDependencyException.Message:Er......
  • K8s集群CoreDNS监控告警最佳实践
    本文分享自华为云社区《K8s集群CoreDNS监控告警最佳实践》,作者:可以交个朋友。一背景coreDNS作为K8s集群中的关键组成部分。主要负责k8s集群中的服务发现,域名解析等功能。如果在使用过程中出现域名解析失败,域名解析超时等情况,需要引起注意。二方案简介可以通过CCE集群插件kub......
  • ARC170C Prefix Mex Sequence
    题意简述有长度为\(n\)的\(s_i=0/1\),求满足下列条件的长度为\(n\)的序列\(a\)的个数,对\(998244353\)取模:\(\foralli,0\lea_i\lem\)当\(s_i=0\)时,\(a_i\not=\operatorname{mex}(a_1,a_2,\cdots,a_{i-1})\)当\(s_i=1\)时,\(a_i=\operatorname{mex}(a_1,a_2,\......