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);
- 注释掉