[TOC]
ChangeTracking
和Saving
Scalar Property
,基元类型属性称为标量属性。每个标量属性映射到数据库表中存储实际数据的列Navigation Property
,导航属性,表示与另一个实体的关系。Reference Navigation Property
,引用导航,实体类A中的某个属性类型是实体类B,对应数据库的表A中新增一个外键列映射表B的主键;Collection Navigation Property
,集合导航,实体类A中的某个属性类型是实体类B的泛型集合,对应数据库的表A的主键映射表B的新增的一个外键;AsNoTracking
不会发生状态改变
,那么可以使用AsNoTracking
方法告诉IQueryable在查询的时候“禁用跟踪”
软删除
domain class
之后需要在DbContext中配置DbSet之后,才能称为实体; ```Csharp public class Student { public int StudentId { get; set; } public string FirstName { get; set; } public string LastName { get; set; }
public int GradeId { get; set; } public Grade Grade { get; set; } }
public class Grade
{
public Grade()
{
Students = new List
public int GradeId { get; set; } public string GradeName { get; set; }
public IList
#### 创建配置DbContext
- 创建一个派生自`DbContext`的上下文类
- 配置实体`DbSet<T>`
- 重载`OnConfiguring()`方法,配置数据库连接字符串
- [Microsoft官方配置](https://learn.microsoft.com/zh-cn/ef/core/dbcontext-configuration/)
- [使用appsettings.json动态配置](https://www.entityframeworktutorial.net/efcore/db-connection-strings.aspx)
```Csharp
public class SchoolContext : DbContext
{
//entities
public DbSet<Student> Students { get; set; }
public DbSet<Grade> Grades { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=SchoolDb;Trusted_Connection=True;");
}
}
Microsoft.EntityFrameworkCore.Tools
Add-Migration InitialCreate
update-database
同上 add & update
Update-database "已经更新到数据库的指定版本"
Remove-Migration "未更新到数据库的无用版本"
Get-Migrations
Script-Migration "迁移版本"
&& generate-migration
using (var context = new SchoolContext())
{
//增加数据
var stdAdd = new Student()
{
FirstName = "Bill",
LastName = "Gates"
};
context.Students.Add(stdAdd);
context.SaveChanges();
//修改数据
var stdUpdate = context.Students.First<Student>();
std.FirstName = "Steve";
context.SaveChanges();
//删除数据
var stdDelete = context.Students.First<Student>();
context.Students.Remove(stdDelete);
context.SaveChanges();
}
//增加数据
var stdAdd = new Student()
{
FirstName = "Bill",
LastName = "Gates"
};
//修改数据
var stdUpdate = new Student()
{
FirstName = "Steve",
LastName = "Gates"
};
//删除数据
var stdDelete = stdUpdate;
using (var context = new SchoolContext())
{
context.Add<Student>(stdAdd);
context.Update<Student>(stdUpdate);
context.Remove<Student>(stdDelete);
context.SaveChanges();
}
Linq to entities
查询Eager Loading
贪婪加载
var context = new SchoolContext();
var student = context.Students
.Where(s => s.FirstName == "Bill")//筛选
.Include(s => s.Grade)//从Student中导航Grade
.ThenInclude(g => g.Teachers)//从Grade中导航Teacher
.FirstOrDefault();
未作为DbSet属性包含但可通过其他DbSet实体中的引用属性访问
的实体创建表。级联删除
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().Property<DateTime>("CreatedDate");
modelBuilder.Entity<Student>().Property<DateTime>("UpdatedDate");
}
using (var context = new SchoolContext())
{
var std = new Student(){ StudentName = "Bill" };
// sets the value to the shadow property
context.Entry(std).Property("CreatedDate").CurrentValue = DateTime.Now;
// gets the value of the shadow property
var createdDate = context.Entry(std).Property("CreatedDate").CurrentValue;
}
希望在SaveChanges()方法上自动为这些shadow属性设置值,这样我们就不必在每个实体对象上手动设置它们。因此,在上下文类中重写SaveChanges()方法; ```Csharp public override int SaveChanges() { var entries = ChangeTracker .Entries() .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);
foreach (var entityEntry in entries) { entityEntry.Property(“UpdatedDate”).CurrentValue = DateTime.Now; if (entityEntry.State == EntityState.Added) { entityEntry.Property(“CreatedDate”).CurrentValue = DateTime.Now; } }
return base.SaveChanges(); } ```
可以一次在所有实体上配置CreatedDate和UpdatedDate,如下所示。 ```Csharp protected override void OnModelCreating(ModelBuilder modelBuilder) { var allEntities = modelBuilder.Model.GetEntityTypes();
foreach (var entity in allEntities) { entity.AddProperty(“CreatedDate”,typeof(DateTime)); entity.AddProperty(“UpdatedDate”,typeof(DateTime)); } } ```
string name = "Bill";
var context = new SchoolContext();
var students = context.Students
.FromSql("Select * from Students where Name = '{0}'", name)
.OrderBy(s => s.StudentId)
.ToList();
name=
开头,可以在app.config中配置)
在第一次运行Code-First应用程序后,您已经创建了一个数据库,那么第二次运行之后呢?
它会在每次运行应用程序时创建一个新的数据库吗?
生产环境如何?
当你改变你的域模型时,你如何改变数据库?
要处理这些场景,必须使用数据库初始化策略之一。