.Net C# 基于EFCore的DBFirst和CodeFirst

DBFirst和CodeFirst

1 概念介绍

1.1 DBFirst(数据库优先)

  • 含义:这种模式是先创建数据库架构,包括表、视图、存储过程等数据库对象。然后通过实体框架(Entity Framework)等工具,根据已有的数据库结构来生成对应的实体类和数据访问代码。
  • 应用场景:当已经存在一个成熟的数据库,例如从旧系统迁移过来的数据库,或者数据库由专业的数据库管理员设计好,开发人员需要基于这个数据库来构建应用程序时,DBFirst 是一个很好的选择。

1.2 CodeFirst(代码优先)

  • 含义:开发人员首先通过编写代码来定义实体类及其之间的关系,如在 C# 中使用实体框架的 CodeFirst 模式。然后,根据这些代码中的定义,实体框架可以自动创建数据库架构或者更新已有的数据库架构来匹配代码中的实体定义。
  • 应用场景:在新项目的开发初期,尤其是团队中有熟练的开发人员能够很好地设计领域模型时,CodeFirst 可以让开发人员专注于业务逻辑和实体关系的构建,而不用担心数据库的细节。它非常适合敏捷开发环境,能够快速迭代数据库架构和应用程序代码。

2 工作流程对比

2.1 DBFirst 工作流程

  1. 数据库设计:数据库管理员(DBA)或者熟悉数据库设计的人员使用数据库管理工具(如 SQL Server Management Studio 等)创建数据库,包括表结构、数据类型、约束条件等。
  2. 生成代码:在 Visual Studio 等开发工具中,使用实体框架的 “从数据库生成模型” 功能,根据数据库结构生成实体类和数据访问上下文(DbContext)类。这些生成的类可以作为数据访问层的基础,开发人员可以在其上添加业务逻辑。
  3. 数据访问和业务逻辑:开发人员在生成的代码基础上,编写业务逻辑方法,如查询、插入、更新和删除数据等操作,将数据访问和业务逻辑结合起来,实现应用程序的功能。

2.2 CodeFirst 工作流程

  1. 实体类定义:开发人员在代码中定义实体类,包括属性、数据类型和实体之间的关系(如一对多、多对多等)。例如,在 C# 中使用实体框架时,通过使用System.ComponentModel.DataAnnotations命名空间中的特性(如[Key]用于定义主键,[Required]用于定义必填字段等)来装饰实体类的属性。
  2. 数据库上下文定义:创建一个继承自DbContext的类,在这个类中定义DbSet属性,用于表示数据库中的表。例如,public DbSet Customers { get; set; }表示一个名为Customers的表,其对应的实体类是Customer。
  3. 数据库迁移(可选但推荐):使用实体框架的迁移功能(如Enable - Migrations和Add - Migration命令)来创建和管理数据库架构的变更。在应用程序启动时,通过调用Database.SetInitializer方法或者在配置文件中设置数据库初始化策略,实体框架可以根据实体类的定义自动创建或者更新数据库。
  4. 数据访问和业务逻辑:与 DBFirst 类似,开发人员在定义好的实体类和数据库上下文基础上,编写业务逻辑方法来实现应用程序的功能。

3 优缺点对比

3.1 DBFirst 优缺点

  • 优点:
    • 对于已有的复杂数据库,能够快速生成对应的代码,节省了大量的实体类和数据访问代码的编写时间。
    • 数据库架构已经确定,开发人员只需要关注应用程序如何使用数据库中的数据,适合数据库结构相对稳定的项目。
  • 缺点:
    • 如果数据库结构发生变化,需要重新生成代码,可能会导致之前对生成代码的修改丢失,需要重新进行合并和调整。
    • 开发人员对数据库结构的依赖较强,在代码中对数据库的更改可能不够灵活,需要在数据库和代码之间频繁切换来进行修改。

3.2 CodeFirst 优缺点

  • 优点:
    • 开发人员可以完全通过代码来控制数据库架构,使得领域模型和代码之间的一致性更好。
    • 便于进行敏捷开发和迭代,当业务需求发生变化时,可以直接在代码中修改实体类的定义,然后通过迁移来更新数据库架构。
  • 缺点:
    • 对于大型的、已有的数据库迁移到 CodeFirst 模式可能比较复杂,需要花费更多的时间来重新设计和实现实体类以及数据访问逻辑。
    • 开发人员需要对实体框架的 CodeFirst 相关知识有深入的了解,如数据库迁移策略、数据注释和流畅 API 等,否则可能会导致数据库架构不符合预期或者出现数据丢失等问题。

4 CoreFirst 示例

4.1 环境搭建

  • 创建项目
    • 创建一个新的.NET 项目(如控制台应用程序或ASP.NET Core Web API 等)。
  • 安装必要的 NuGet 包
    • 安装Npgsql.EntityFrameworkCore.PostgreSQL包。这个包允许你在 Entity Framework Core 中使用 PostgreSQL 数据库。可以通过在项目目录下的命令行中执行dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL来安装。

4.2 定义实体类

  • Blog 类

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    namespace BloggingApp
    {[Table("blogs")]public class Blog{[Key]public int BlogId { get; set; }[Required][StringLength(100)]public string Name { get; set; }public DateTime CreatedDate { get; set; } = DateTime.Now;public IList<Post> Posts { get; set; } = new List<Post>();}
    }
    
    • 解释:
      • [Table("blogs")]指定实体类对应的数据库表名为blogs
      • [Key]定义BlogId为表的主键。
      • [Required][StringLength(100)]用于验证Name属性,确保其为必填且长度不超过 100。
      • CreatedDate默认为当前日期时间,表示博客的创建时间。
      • Posts是一个IList<Post>类型的属性,表示一篇博客可以有多篇文章(Post)与之关联。
  • Post 类

    [Table("posts")]
    public class Post
    {[Key]public int PostId { get; set; }[Required][StringLength(200)]public string Title { get; set; }public string Content { get; set; }public DateTime PublishedDate { get; set; } = DateTime.Now;public int BlogId { get; set; }[ForeignKey("BlogId")]public Blog Blog { get; set; }public IList<Comment> Comments { get; set; } = new List<Comment>();
    }
    
    • 解释:
      • [Table("posts")]表示对应的数据库表是posts
      • [Key]定义PostId为主键。
      • Title是文章标题,Content是文章内容,PublishedDate默认为当前时间,表示发布日期。
      • BlogId是外键,通过[ForeignKey("BlogId")]特性关联到Blog类的BlogIdBlog属性表示这篇文章所属的博客。
      • Comments是一个IList<Comment>类型的属性,表示一篇文章可以有多个评论(Comment)。
  • Comment 类

    [Table("comments")]
    public class Comment
    {[Key]public int CommentId { get; set; }[Required]public string Content { get; set; }public DateTime CommentedDate { get; set; } = DateTime.Now;public int PostId { get; set; }[ForeignKey("PostId")]public Post Post { get; set; }
    }
    
    • 解释:
      • [Table("comments")]表示对应的数据库表是comments
      • [Key]定义CommentId为主键。
      • Content是评论内容,CommentedDate默认为当前时间,表示评论日期。
      • PostId是外键,通过[ForeignKey("PostId")]特性关联到Post类的PostIdPost属性表示这个评论所属的文章。

4.3 创建数据库上下文类

using Microsoft.EntityFrameworkCore;
namespace BloggingApp
{public class BloggingContext : DbContext{public BloggingContext(DbContextOptions<BloggingContext> options) : base(options){}public DbSet<Blog> Blogs { get; set; }public DbSet<Post> Posts { get; set; }public DbSet<Comment> Comments { get; set; }}
}
  • 解释:
    - 构造函数接受DbContextOptions<BloggingContext>类型的参数,并传递给基类DbContext的构造函数。
    - DbSet<Blog> BlogsDbSet<Post> PostsDbSet<Comment> Comments分别定义了对应数据库表的属性,用于操作blogspostscomments表。

4.4 配置数据库连接字符串

  • appsettings.json文件中添加以下内容:
{"ConnectionStrings": {"BloggingDbConnection": "Host=localhost;Database=blogging_app;Username=postgres;Password=your_password"}
}
  • 注意:

    • 你需要将your_password替换为你实际的 PostgreSQL 数据库密码。
    • Host是数据库服务器地址,Database是数据库名称,Username是登录用户名。
  • Program.cs(如果是控制台应用程序)或Startup.cs(如果是ASP.NET Core 应用程序)中读取连接字符串并配置数据库上下文:

    • 对于控制台应用程序,在Program.cs中:
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using System.IO;
    class Program
    {static void Main(){var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);IConfigurationRoot configuration = builder.Build();var connectionString = configuration.GetConnectionString("BloggingDbConnection");var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>().UseNpgsql(connectionString);using (var context = new BloggingContext(optionsBuilder.Options)){// 在这里可以进行数据库操作,如插入、查询等}}
    }
    
    • 对于ASP.NET Core 应用程序,在Startup.cs中:
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    public class Startup
    {public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }public void ConfigureServices(ServiceCollection services){var connectionString = Configuration.GetConnectionString("BloggingDbConnection");services.AddDbContext<BloggingContext>(options =>options.UseNpgsql(connectionString));// 其他服务配置}// 其他方法
    }
    

4.5 数据库迁移和操作

  • 安装EF工具

    • 安装全局工具 dotnet tool install --global dotnet-ef
    • 更新工具 dotnet tool update --global dotnet-ef
  • 添加迁移(假设是初始创建)

    • 在命令行中执行dotnet ef migrations add InitialCreate
  • 更新数据库

    • 在命令行中执行dotnet ef database update
  • 数据库操作示例 - 插入数据

    • using块中(对于控制台应用程序)或在服务方法中(对于ASP.NET Core 应用程序)插入数据:
    using (var context = new BloggingContext(optionsBuilder.Options))
    {var blog = new Blog{Name = "My Awesome Blog"};var post = new Post{Title = "First Post",Content = "This is the content of my first post.",Blog = blog};var comment = new Comment{Content = "Great post!",Post = post};context.Blogs.Add(blog);context.Posts.Add(post);context.Comments.Add(comment);context.SaveChanges();
    }
    
  • 解释:

    • 首先创建一个Blog对象,然后创建一个Post对象并关联到前面的Blog,接着创建一个Comment对象并关联到Post
    • 通过context.Blogs.Addcontext.Posts.Addcontext.Comments.Add将这些对象添加到相应的数据库表中。
    • 最后,通过context.SaveChanges将更改保存到数据库。

5 DBFirst 示例

5.1 生成数据库上下文和实体类

  • 打开命令行工具,执行dotnet ef dbcontext scaffold "Host=localhost;Port=5432;Database=your_database_name;Username=postgres;Password=your_password" Npgsql.EntityFrameworkCore.PostgreSQL -o Models
    • 解释:
      • 这个命令根据指定的 PostgreSQL 数据库连接字符串和提供程序(Npgsql.EntityFrameworkCore.PostgreSQL)来生成数据库上下文和实体类,并输出到Models文件夹下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/59070.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

链表详解(三)

目录 链表功能实现链表的查找SLNode* SLFind(SLNode* phead, SLNDataType x)代码 链表任意位置前插入void SLInsert(SLNode**pphead&#xff0c;SLNode* pos, SLNDataType x)代码 链表任意位置前删除void SLErase(SLNode**pphead&#xff0c;SLNode* pos)代码 链表任意位置后插…

《C#语法一篇通》,20万字,48小时阅读,持续完善中。。。

本文摘录了C#语法的主要内容&#xff0c;接近20万字。 所有鸡汤的味道都等于马尿&#xff01; 如果你相信任何所谓的鸡汤文章&#xff0c;智商堪忧。 计算机语言没有”好不好“之说&#xff0c;骗子才会告诉你哪个语言好&#xff0c;学好任何一本基础语言&#xff08;C&#…

HarmonyOS开发 - 餐饮APP中多门店多窗口打开实例补充

specified启动模式为指定实例模式&#xff0c;有一些特殊场景&#xff0c;例如多门店应用中每次打开一个门店都希望能新建一个门店实例&#xff0c;而重复打开同一个门店都是同一门店实例。 此篇为餐饮APP中多门店实例的补充内容&#xff0c;以解决同一门店多次点击重复创建新窗…

Lammps动态删除反应产物分子的方法

大家好,我是小马老师。 本文介绍lammps反应势模拟过程中动态删除产物分子的方法。 lammps reaxff反应势可以模拟分子间的化学反应,fix reaxff/species命令可以输出反应过程中的产物信息。 在2022之后的lammps版本中,这个命令新增了delete关键词,使用这个命令,可以动态删除…

【Redis问题】(error) NOAUTH Authentication required.解决方法

问题描述&#xff1a; “(error) NOAUTH Authentication required”&#xff0c;通过ping方法和redis打招呼发现不成功&#xff0c;意思是没有这个权限&#xff08;也就是没有密码&#xff09; 问题解决1&#xff1a; 在命令后面加上密码&#xff08;一般情况下&#xff0c;在…

css 在 hover 子元素时,不要让父元素触发 hover 效果

别人写的没看到一个能好用的&#xff0c;虽然功能简单&#xff0c;但是这个应该还是比较陌生的 希望帮到你&#xff0c;能帮我点个赞 废话不多书&#xff0c;直接出代码 <div class"parent"><div class"child">悬停我</div></div&g…

关于自动化测试用例失败重试的一些思考

自动化测试用例失败重跑有助于提高自动化用例的稳定性&#xff0c;那我们来看一下&#xff0c;python和java生态里都有哪些具体做法&#xff1f; 怎么做 如果是在python生态里&#xff0c;用pytest做测试驱动&#xff0c;那么可以通过pytest的插件pytest-rerunfailures来实现…

Vue Router进阶详解

导航守卫 若依框架登录鉴权详解&#xff08;动态路由&#xff09;_若依鉴权-CSDN博客 完整的导航解析流程 导航被触发&#xff1a; 当用户点击页面中的链接、使用编程式导航&#xff08;如router.push或router.replace&#xff09;或手动输入URL时&#xff0c;导航流程被触发。…

如何把子组件的v-model修改数据,进行接收然后定义数据格式,子传父的实现

在 Vue 中&#xff0c;实现子组件通过 v-model 向父组件传递数据并接收后进行格式化&#xff0c;可以按照以下步骤来封装和实现&#xff1a; 步骤 1: 子组件实现 v-model 子组件需要定义一个 props 来接收 v-model 的值&#xff0c;并通过 emit 方法发出更新事件。 <!-- …

Rust 力扣 - 1984. 学生分数的最小差值

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 原数组 nums 排序&#xff0c;遍历nums中下标为[0, nums.len() - k]的学生分数 假设当前遍历的下标为i则&#xff0c;以 i 下标为最小值的学生分数的最小差值为nums[i k - 1] - nums[i] 取最小差值的最小值即…

distrobox install in ubuntu 22.04 / 在 ubuntu 22.04 上安装 distrobox (***) OK

要点&#xff1a; 本测试实验&#xff0c;采用的是 podman distrobox 在沙盒 snap 中&#xff0c;安装 distrobox 需要使用 --devmode 开发模式&#xff1b;可以避开 distrobox 的版本检查&#xff1f; distrobox 官方文档显示&#xff0c; Installation https://distrobox.i…

【k8s】-运维技巧-1

文章目录 k8s-节点驱逐节点驱逐节点删除批量删除镜像k8sdockerdocker 删除缓存k8s异常Pod清理删除所有命名空间下非Running状态的 Pod强制删除所有命名空间下非Running状态的 Podk8s-节点驱逐 节点驱逐 kubectl cordon k8s-node1 kubectl drain k8s-node1 --delete-local-dat…

开源数据库 - mysql - 基于GTID的主备部署

GTID AUTO_POSITION MODE的主从 搭建主从模式 注意&#xff0c;主备库必须开启GTID并设置好server_id&#xff1a; enforce_gtid_consistency ON # 开启强制GTID一致性&#xff0c;防止非GTID事务复制 gtid_mode ON # 开启GTID server_id 9910 # 主主或者主从配置必须不一…

IA应用加速,让电子供应链更智能高效

在当今数字化浪潮中&#xff0c;电子产品制造行业正经历着前所未有的变革。越来越多的企业开展全球化业务&#xff0c;进行数字化转型&#xff0c;对于网络时延的需求也更高。 客户背景 客户专注于为中小微电子产品制造企业提供产品技术方案开发、电子元器件采购、PCBA生产制造…

git 删除远程不存在本地命令却能看到的分支

要删除远程不存在但本地却能看到的分支&#xff0c;你可以按照以下步骤操作&#xff1a; 删除本地分支&#xff1a; 如果你确定要删除的分支已经没有用处&#xff0c;可以使用以下命令来删除本地分支&#xff1a; git branch -d <branch-name>这里的 <branch-name>…

2024年11月4日Github流行趋势

项目名称&#xff1a;DS4SD / docling 项目维护者&#xff1a;dolfim-ibm, github-actions, vagenas, cau-git, PeterStaar-IBM 项目介绍&#xff1a;让您的文档准备好迎接生成式AI。 项目star数&#xff1a;3,906 项目fork数&#xff1a;221 项目名称&#xff1a;abi / scree…

从模糊搜索到语义搜索的进化之路——探索 Chroma 在大模型中的应用价值

目录 从模糊搜索到语义搜索的进化之路——探索 Chroma 在大模型中的应用价值 一、引言 二、实现语义搜索的数据库 Chroma 1、语义搜索是什么 2、Chroma 语义搜索的原理 三、如何在项目中应用 Chroma 1、Chroma 的实际应用场景 2、安装Chroma&#xff08;python环境&…

iOS灵动岛动画小组件怎么播放动画

这个灵动岛相关的展示位置分几个地方&#xff1a; 紧凑型&#xff0c;最小化&#xff0c;扩展型&#xff0c;还有锁屏位置 我们先来看一下我这边实现的动画效果 demo下载&#xff1a; iOS灵动岛GIF动画 灵动岛样式 灵动岛有三种渲染模式&#xff1a; 第一种是 紧凑型&…

网络信息系统的整个生命周期

网络信息系统规划 此阶段主要是根据企业的业务需求、技术发展趋势以及市场环境等因素&#xff0c;对网络信息系统进行初步的规划和设计。规划的内容可能包括系统的目标、功能、性能、安全性等方面的要求。 规划阶段还需要进行可行性研究&#xff0c;评估项目在技术、经济、社…

力扣排序268题 数字丢失

题目&#xff1a; 丢失的数字 给定一个包含[0,n]中n各数的数组nums&#xff0c;找出[0,n]这个范围 内没有出现在数组中的那个数。 示例1&#xff1a; 输出&#xff1a;n 3,因为有3个数字&#xff0c;所以所有的数字都在范围 [0,3]内。2是丢失的数字&#xff0c;因为它没有出现…