EFCore数据迁移
数据迁移
初始化
Code First
首先创建
DbContext
,使用以下命令添加迁移,初始化数据库。1
2dotnet ef migrations add <migration name>
dotnet ef database updateData First
根据 已经存在 的数据库,使用以下命令创建数据库上下文与实体类
1
dotnet ef dbcontext scaffold <connection string> <provider(E.g. Microsoft.EntityFrameworkCore.SqlServer)>
Tip :
dotnet ef --help
,dotnet ef migrations --help
,dotnet ef database --help
,dotnet ef dbcontext --help
。这些命令可以查询其他配置。dotnet-ef命令行官方文档(.NET Core CLI)
字段的特性
FullName
没有Set
方法,不会再数据库新建这个列
1 | using System; |
导航属性,如果是集合,类型可以是
ICollection<T>
,HashSet<T>
,List<T>
。如果设置为ICollection<T>
,EF 默认是一个HashSet<T>
1 | public ICollection<CourseAssignment> CourseAssignments { get; set; } |
Instructor
与OfficeAssignment
关系为 1 - 0…1,意味着讲师可能没有办公室。InstructorID
是外键,同时也是主键
,EF只能识别为外键,[Key]
这个特性将InstructorID
标志为主键
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class OfficeAssignment
{
[ ]
public int InstructorID { get; set; }
[ ]
[ ]
public string Location { get; set; }
public Instructor Instructor { get; set; }
}
}
[DatabaseGenerated(DatabaseGeneratedOption.None)]
设置主键不由数据库自动生成。在课程这个表中,CourseID
可能需要极大力度的用户自定义,比如 A课程是 1000 ,B课程是 2000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class Course
{
[ ]
[ ]
public int CourseID { get; set; }
[ ]
public string Title { get; set; }
[ ]
public int Credits { get; set; }
public int DepartmentID { get; set; }
public Department Department { get; set; }
public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<CourseAssignment> CourseAssignments { get; set; }
}
}
指定一个货币类型的列。2333…mysql不支持
money
,应该换为float(9,2)
1
2 [ ]
public decimal Budget { get; set; }
可空字段,作为外键。如果非空呢?EF默认层级删除,意味着删除外键id指向的数据,会同时删除外键所在表对应数据。
1 | public int? InstructorID { get; set; } |
fluent API 取消严格的层级删除
1
2
3
4 modelBuilder.Entity<Department>()
.HasOne(d => d.Administrator)
.WithMany()
.OnDelete(DeleteBehavior.Restrict)
只能使用fluent API 设置复合主键
1
2 modelBuilder.Entity<CourseAssignment>()
.HasKey(c => new { c.CourseID, c.InstructorID });
记一次迁移失败
错误原因
Course
(原来已有数据),添加一列DepartmentID
,此列非空,并且Department
表还未创建。DepartmentID
默认是外键,存在外键约束。 EF在迁入的时候不知道,不知道给一个什么默认值,所以报错。外键约束
FOREIGN KEY
约束用于预防破坏表之间连接的动作。
FOREIGN KEY
约束也能防止非法数据插入外键列,因为它 必须是它指向的那个表中的值之一。错了怎么回滚
在数据库中迁移表添加一行记录,错的这个版本的。这里是
20180411020802_ComplexDataModel
,假装这次迁移已经成功……| MigrationId | ProductVersion |
| :—–: | :—: |
| 20180410142846_InitialCreat | 2.0.1-rtm-125 |
| 20180410152220_MaxLengthOnNames | 2.0.1-rtm-125 |
| 20180410152629_ColumnFirstName | 2.0.1-rtm-125 |
| 20180410153611_ColumnSetRequied | 2.0.1-rtm-125 |
| 20180411020802_ComplexDataModel | 2.0.1-rtm-125 |执行
dotnet ef database update <last version>
,当然你要保证这一版本的Down
方法里面的正确性(有些Up
方法里的可能还没执行到,需要注释Down
方法里部分)1
dotnet ef database update ColumnSetRequied
解决外键的问题
- 注释掉
Up
方法里的添加DepartmentID
的 - 在创建
Department
这个表之后,添加以下1
2
3
4
5
6
7
8
9migrationBuilder.Sql("INSERT INTO dbo.Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())");
// Default value for FK points to department created above, with
// defaultValue changed to 1 in following AddColumn statement.
migrationBuilder.AddColumn<int>(
name: "DepartmentID",
table: "Course",
nullable: false,
defaultValue: 1);
- 注释掉