本文将详细讲解EF Core与MySQL的关系配置和迁移,包括一对一、一对多、多对多关系的配置,使用Fluent API进行关系配置,处理迁移中的常见问题,以及数据种子的方法。

1. EF Core 中的关系类型

Entity Framework Core 支持三种主要的关系类型:

一对一关系 (One-to-One)

一个实体实例只与另一个实体实例相关联。例如:一个用户有一个用户资料。

public class User
{
public int Id { get; set; }
public string Username { get; set; }
public UserProfile Profile { get; set; } // 导航属性
} public class UserProfile
{
public int Id { get; set; }
public string FullName { get; set; }
public DateTime DateOfBirth { get; set; }
public int UserId { get; set; } // 外键
public User User { get; set; } // 导航属性
}

一对多关系 (One-to-Many)

一个实体实例与多个另一个实体实例相关联。例如:一个博客有多篇文章。

public class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public List<Post> Posts { get; set; } // 导航属性
} public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; } // 外键
public Blog Blog { get; set; } // 导航属性
}

多对多关系 (Many-to-Many)

多个实体实例与多个另一个实体实例相关联。例如:一个学生可以选多门课程,一门课程可以有多个学生。

public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public List<Course> Courses { get; set; } // 导航属性
} public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public List<Student> Students { get; set; } // 导航属性
} // 连接实体(EF Core 5.0+ 可以隐式处理,但显式定义更灵活)
public class StudentCourse
{
public int StudentId { get; set; }
public Student Student { get; set; }
public int CourseId { get; set; }
public Course Course { get; set; }
public DateTime EnrollmentDate { get; set; }
}

2. 使用 Fluent API 配置关系

Fluent API 提供了更精细的控制方式来配置关系:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 一对一关系配置
modelBuilder.Entity<User>()
.HasOne(u => u.Profile)
.WithOne(up => up.User)
.HasForeignKey<UserProfile>(up => up.UserId); // 一对多关系配置
modelBuilder.Entity<Blog>()
.HasMany(b => b.Posts)
.WithOne(p => p.Blog)
.HasForeignKey(p => p.BlogId)
.OnDelete(DeleteBehavior.Cascade); // 级联删除 // 多对多关系配置 (EF Core 5.0+)
modelBuilder.Entity<Student>()
.HasMany(s => s.Courses)
.WithMany(c => c.Students)
.UsingEntity<StudentCourse>(
j => j.HasOne(sc => sc.Course).WithMany().HasForeignKey(sc => sc.CourseId),
j => j.HasOne(sc => sc.Student).WithMany().HasForeignKey(sc => sc.StudentId),
j =>
{
j.HasKey(sc => new { sc.StudentId, sc.CourseId });
j.Property(sc => sc.EnrollmentDate).HasDefaultValueSql("CURRENT_TIMESTAMP");
}); // 配置索引
modelBuilder.Entity<Post>()
.HasIndex(p => p.Title)
.IsUnique(); // 配置表名和列名
modelBuilder.Entity<User>()
.ToTable("Users")
.Property(u => u.Username)
.HasColumnName("user_name")
.HasMaxLength(50);
}

3、EF Core 配置字段长度或精度

在Entity Framework Core (EF Core)中,配置字段长度或精度涉及到如何在模型中指定数据库列的属性。EF Core通过数据注解(Data Annotations)或Fluent API提供了多种方式来实现这一需求。下面将分别介绍如何使用这两种方法。

使用数据注解

在模型类中,你可以使用如[MaxLength][Column]等属性来指定字段的长度或精度。

  • 示例:使用[MaxLength]
using System.ComponentModel.DataAnnotations;

public class Product
{
public int Id { get; set; } [MaxLength(100)]
public string Name { get; set; }
}
  • 示例:使用[Column]

using System.ComponentModel.DataAnnotations.Schema;

public class Product
{
  public int Id { get; set; }   [Column(TypeName = "varchar(100)")]
  public string Name { get; set; }
}

使用Fluent API

在DbContext的OnModelCreating方法中,你可以使用Fluent API来配置字段的长度或精度。

  • 示例:使用Fluent API配置字段长度
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>(entity =>
{
entity.Property(e => e.Name)
.HasMaxLength(100);
});
}
  • 示例:使用Fluent API指定列类型(包括精度和长度)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>(entity =>
{
entity.Property(e => e.Price)
.HasColumnType("decimal(18,2)"); // 例如,设置价格字段为decimal类型,总共18位,其中2位是小数部分
       //.HasPrecision(18, 2); // 确保同时使用HasPrecision来指定精度和长度
});
}

注意事项

  • 数据类型映射:确保你指定的数据类型与数据库中的类型兼容。例如,使用decimal(18,2)时,确保数据库支持这种类型。对于不支持的类型,如某些NoSQL数据库,可能需要自定义存储方式。

  • 迁移:当你修改了模型并希望更新数据库时,确保运行了迁移命令(如Add-MigrationUpdate-Database)。EF Core会根据模型中的配置自动生成或更新数据库表结构。

  • 性能和设计:在设计数据库和模型时,考虑到性能和设计需求。例如,对于非常大的文本字段,使用TEXT类型而非VARCHAR(N)可以更高效地存储大量文本数据。

通过以上方法,你可以灵活地配置EF Core中的字段长度或精度,以适应不同的应用需求。

4. 处理迁移中的常见问题

创建和应用迁移

# 创建迁移
dotnet ef migrations add AddRelationships # 应用迁移
dotnet ef database update # 回滚迁移
dotnet ef database update PreviousMigrationName # 删除最后一次迁移
dotnet ef migrations remove

解决迁移冲突

当多个开发人员同时创建迁移时,可能会产生冲突。解决方法:

  1. 协调团队成员,确保一次只有一个人创建迁移

  2. 使用 dotnet ef migrations script 生成SQL脚本,手动合并更改

  3. 删除冲突的迁移,重新创建

处理模型更改后的迁移

当模型更改后,EF Core 可能无法自动检测所有更改。解决方法:

  1. 仔细检查生成的迁移代码

  2. 手动修改迁移文件以包含所有必要的更改

  3. 使用 dotnet ef migrations add 创建新的迁移

处理外键约束问题

// 在迁移中处理外键约束
migrationBuilder.AddForeignKey(
name: "FK_Posts_Blogs_BlogId",
table: "Posts",
column: "BlogId",
principalTable: "Blogs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);

处理MySQL特定的迁移问题

// 在迁移中处理MySQL特定配置
migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Posts",
type: "varchar(255)",
maxLength: 255,
nullable: false,
collation: "utf8mb4_unicode_ci",
oldClrType: typeof(string),
oldType: "longtext",
oldNullable: false)
.Annotation("MySql:CharSet", "utf8mb4");

5. 数据种子 (Seed Data)

在迁移中配置种子数据

// 在迁移的Up方法中添加种子数据
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "Blogs",
columns: new[] { "Id", "Title" },
values: new object[] { 1, "Default Blog" });
} // 在迁移的Down方法中移除种子数据
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "Blogs",
keyColumn: "Id",
keyValue: 1);
}

在DbContext中配置种子数据

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>().HasData(
new Blog { Id = 1, Title = "Default Blog" },
new Blog { Id = 2, Title = "Secondary Blog" }
); modelBuilder.Entity<Post>().HasData(
new Post { Id = 1, Title = "First Post", Content = "Hello World", BlogId = 1 },
new Post { Id = 2, Title = "Second Post", Content = "EF Core is awesome", BlogId = 1 }
);
}

使用自定义初始化逻辑

public static class DbInitializer
{
public static void Initialize(ApplicationDbContext context)
{
// 确保数据库已创建
context.Database.EnsureCreated(); // 检查是否已有数据
if (context.Blogs.Any())
{
return; // 数据库已经 seeded
} // 添加初始数据
var blogs = new Blog[]
{
new Blog{Title="Technology Blog"},
new Blog{Title="Food Blog"}
}; foreach (var blog in blogs)
{
context.Blogs.Add(blog);
}
context.SaveChanges(); var posts = new Post[]
{
new Post{Title="Introduction to EF Core", Content="...", BlogId=1},
new Post{Title="Best Pizza Recipe", Content="...", BlogId=2}
}; foreach (var post in posts)
{
context.Posts.Add(post);
}
context.SaveChanges();
}
}

在应用程序启动时调用初始化

// 在Program.cs或Startup.cs中
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build(); using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<ApplicationDbContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
} host.Run();
}

6. 处理复杂场景

条件种子数据

public static void Initialize(ApplicationDbContext context)
{
// 只在开发环境中添加测试数据
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
{
if (!context.Blogs.Any())
{
context.Blogs.AddRange(
new Blog { Title = "Test Blog 1" },
new Blog { Title = "Test Blog 2" }
);
context.SaveChanges();
}
} // 在所有环境中添加必要的基础数据
if (!context.Roles.Any())
{
context.Roles.AddRange(
new Role { Name = "Administrator" },
new Role { Name = "User" }
);
context.SaveChanges();
}
}

使用JSON文件存储种子数据

public static void Initialize(ApplicationDbContext context)
{
if (!context.Blogs.Any())
{
var seedDataPath = Path.Combine(Directory.GetCurrentDirectory(), "SeedData");
var blogsJson = File.ReadAllText(Path.Combine(seedDataPath, "blogs.json"));
var blogs = JsonSerializer.Deserialize<List<Blog>>(blogsJson); context.Blogs.AddRange(blogs);
context.SaveChanges();
}
}

总结

本文详细介绍了EF Core与MySQL中的关系配置、迁移处理和种子数据管理。关键点包括:

  1. 使用Fluent API精细配置一对一、一对多和多对多关系

  2. 正确处理迁移创建、应用和回滚

  3. 解决迁移过程中的常见问题

  4. 使用多种方法添加和管理种子数据

  5. 处理复杂场景如条件种子数据和外部数据源

正确配置关系和迁移是构建健壮数据访问层的关键,而合理的种子数据策略可以大大简化开发和测试过程。

EF Core 与 MySQL:迁移和关系配置详解的更多相关文章

  1. mysql group replication 安装&配置详解

    一.原起: 之前也有写过mysql-group-replication (mgr) 相关的文章.那时也没有什么特别的动力要写好它.主要是因为在 mysql-5.7.20 之前的版本的mgr都有着各种各 ...

  2. MySQL数据库安装与配置详解

    转载提示:在原文http://www.cnblogs.com/sshoub/p/4321640.html基础上修改. 目录 一.概述 二.MySQL安装 三.安装成功验证 四.NavicatforMy ...

  3. Win下 MySQL数据库安装与配置详解

    第一步 从官网下载安装包 (本次只写安装版的32位的mysql) 1. https://www.mysql.com/downloads/ 下载的官网地址 一直滑到最下面 然后点第一个 然后选第一个 这 ...

  4. MySQL数据库安装与配置详解(图文)

    接下来看一下如何安装mysql数据库. 由于有更详细的教程资源,因此参考别人的文章以整理.安装教程参考自博客园文章http://www.cnblogs.com/sshoub/p/4321640.htm ...

  5. Mysql 数据库安装与配置详解

    目录 一.概述 二.MySQL安装 三.安装成功验证 四.NavicatforMySQL下载及使用 一.概述 MySQL版本:5.7.17 下载地址:http://rj.baidu.com/soft/ ...

  6. 阿里云、腾讯云、CentOS下的MySQL的安装与配置详解

    一. 安装 查看是否已安装 # 查看MySQL版本 mysql --version # 查看MySQL相关文件 whereis mysql 若已安装,卸载方法如下 # 卸载MySQL yum remo ...

  7. ASP.NET Core使用EF Core操作MySql数据库

    ASP.NET Core操作MySql数据库, 这样整套环境都可以布署在Linux上 使用微软的 Microsoft.EntityFrameworkCore(2.1.4) 和MySql出的 MySql ...

  8. 谈谈EF Core实现数据库迁移

    作为程序员,在日常开发中,记忆犹新的莫过于写代码,升级程序.升级程序包含两部分:一是,对服务程序更新:二是,对数据库结构更新.本篇博文主要介绍数据库结构更新,在对数据库升级时,不知道园友们是否有如下经 ...

  9. 第八节:EF Core连接MySql数据库

    一. 前提 1.安装EF Core连接MySQL的驱动,这里有两类: (1).Oracle官方出品:MySql.Data.EntityFrameworkCore (版本:8.0.17) (2).其他第 ...

  10. ASP.NET Core MVC+Layui使用EF Core连接MySQL执行简单的CRUD操作

    前言: 本章主要通过一个完整的示例讲解ASP.NET Core MVC+EF Core对MySQL数据库进行简单的CRUD操作,希望能够为刚入门.NET Core的小伙伴们提供一个完整的参考实例.关于 ...

随机推荐

  1. 从零开始实现简易版Netty(三) MyNetty 高效的数据读取实现

    从零开始实现简易版Netty(三) MyNetty 高效的数据读取实现 1. MyNetty 数据读取处理优化 在上一篇博客中,lab2版本的MyNetty实现了基本的reactor模型和一个简易的p ...

  2. java group Layout 组框架

    简介 https://netbeans.org/features/java/swing.html 里面有一个mattise 专门用来生成布局代码 GroupLayout code 代码先不贴了

  3. Absolute 如何实现居中

    简介 html 中 absolute 元素如何实现居中,因为CSDN链接也很稳定就不贴了,留作备份 参考链接 & 实现 https://blog.csdn.net/HatOfDragon/ar ...

  4. SciTech-OS-Linux-Device Driver: 英文原版电子书“Linux Device Drivers, Third Edition”

    https://lwn.net/Kernel/LDD3/ Linux Device Drivers, Third EditionThis is the web site for the Third E ...

  5. longchain4j 学习系列(1)-ollama本地调用

    longchain4j是比spring-ai更早出现的大模型相关工程开源框架,社区成熟,活跃度高.下面演示如何用longchain4j调用本地ollama 一.核心pom依赖 1 <!-- Lo ...

  6. 【机器人】—— 2. ROS 集成开发环境配置

    和大多数开发环境一样,理论上,在 ROS 中,只需要记事本就可以编写基本的 ROS 程序,但是工欲善其事必先利其器,为了提高开发效率,可以先安装集成开发工具和使用方便的工具:终端.IDE.... 1. ...

  7. 为大模型 MCP Code Interpreter 而生:C# Runner 开源发布

    在7月初,我立下了一个 Flag:要做一个专门为大语言模型(LLM)设计的 C# 运行器 MCP (Model-Protocol-Context).我的小小执念,是希望 C# 能够像 Python 一 ...

  8. luogu P1048 [NOIP2005 普及组] 采药

    [NOIP2005 普及组] 采药 题目描述 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给他出了一个难题.医师把他带到一个到处 ...

  9. spring 的aop面试题

  10. GIS兼职日记-持续连载

    技术栈 lth 编写时间:2025-08-15 更新时间:2025-08-15 SLDPRT转GEOJSON 客户需求和拆解 客单价130RMB SLDPRT转GEOJSON想在web展示,那么我们主 ...