.net core EF 关系(一) 一对多 映射配置
参考 一对多关系 - EF Core | Microsoft Learn
关系映射 最难得就是一对多 ,剩下得多对多 一对一看看就行
blog类是 一端 post 类多端
映射关系 | |||||
一端 和多端都有导航属性 多端有外键 | builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.BlogId).IsRequired(); | ||||
一端和多端都有导航属性 多端有外键 ,多端外键可null 多端导航属性可null | builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.Id).IsRequired(false); | ||||
一端和多端都有导航属性,多端没有外键,必须存在关系 | builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired(); | ||||
一端和多端都有导航属性,多端没有外键,存在关系可null |
//设置外键名称 BlogId builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired(false)
//这种 外键自动生成 BlogId builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).IsRequired(false); |
||||
一端只有导航属性多端没有导航属性,多端只有外键 | builder.HasMany(x => x.Posts).WithOne().HasForeignKey(x=>x.BlogId).IsRequired(); | ||||
一端只有导航属性多端没有导航属性,多端只有外键,多端外键可null | builder.HasMany(x => x.Posts).WithOne().HasForeignKey(x=>x.BlogId).IsRequired(false); | ||||
一端和多端都没有导航属性,多端只有外键 | builder.HasMany<Post>().WithOne().HasForeignKey(x => x.BlogId).IsRequired(); | ||||
备选键 |
注意 如果一对多 两端都只有导航属性配置
可以 如下配置 那么会有一个问题 外键如何访问? 使用 EF.Property<int>(x, "BlogId") 访问
不明白可以查看 阴影和索引器属性 - EF Core | Microsoft Learn 这里详细讲解了 如何配置和访问
//设置外键名称 BlogId builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired(false) //这种 外键自动生成 BlogId builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).IsRequired(false);
下面配置的该情况 可以看到 一端 多端 都只有导航属性 没有配置外键
/// <summary> /// 博客 /// </summary> public class Blog { public Blog() { } public Blog(string url) { _url = url; } public int Id { get; set; } private IEnumerable<Post> _posts; /// <summary> /// 导航属性发布集合 /// </summary> public IEnumerable<Post> Posts => _posts ??= new List<Post>(); /// <summary> /// 私有字段 /// </summary> private string _url; /// <summary> /// 属性 /// </summary> public string Url => _url; /// <summary> /// 私有字段 /// </summary> private string soltCode ="solt"; } /// <summary> /// 发布 /// </summary> public class Post { public int Id { get; set; } public string Name { get; set; } ///// <summary> ///// 外键 博客Id ///// </summary> //public int BlogId { get; set; } /// <summary> /// 导航属性Blog /// </summary> public Blog? Blog { get; set; } }
关系配置 需要单独配置
//配置阴影属性 外键
builder.Property<int>("BlogId");
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder.ToTable("T_Blogs");
builder.HasKey(x => x.Id);
//博客和发布时一对多 导航属性 Blog 不为null 外键博客BlogId 必须存在关系 IsRequired() 默认为true
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.BlogId).IsRequired();
//博客和发布时一对多 导航属性 Blog 为null 外键为null 博客BlogId 必须存在关系 IsRequired(false)
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.Id).IsRequired(false);
//博客和发布时一对多 只有导航属性 Blog 没有外键 的必须存在关系IsRequired()
// builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired();
//博客和发布时一对多 只有导航属性 Blog 没有外键 的必须存在关系IsRequired(false)
// builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired(false);
//博客和发布时一对多 Blog有导航属性 Post没有有导航属性 Blog 只有有外键 的必须存在关系IsRequired()
// builder.HasMany(x => x.Posts).WithOne().HasForeignKey(x=>x.BlogId).IsRequired();
//博客和发布时一对多 Blog没有有导航属性 只有有外键 的必须存在关系IsRequired()
builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).IsRequired(false);
//私有字段
//builder.Property(x => x.Url).HasField("_url");
builder.Property(x=>x.Url).HasField("_url").UsePropertyAccessMode(PropertyAccessMode.Field);
builder.Property("soltCode").HasColumnName("SoltCode");
var navigation = builder.Metadata.FindNavigation(nameof(Blog.Posts));
navigation.SetPropertyAccessMode(PropertyAccessMode.Field);
}
}
public class PostEntityTypeConfiguration : IEntityTypeConfiguration<Post>
{
public void Configure(EntityTypeBuilder<Post> builder)
{
builder.ToTable("T_Post");
builder.HasKey(x => x.Id);
//配置阴影属性
builder.Property<int>("BlogId");
}
}
访问使用 EF.Property<int>(x, "BlogId")
例如
/// <summary>
/// 查询
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Blog> FindByIdAsync(int id)
{
//通过阴影属性查询
Blog blog = await _context.Blogs.Include(x =>
x.Posts.Where(x => EF.Property<int>(x, "BlogId") == id)).AsNoTracking().FirstOrDefaultAsync(x => x.Id == id);
return blog;
}
=============================================================================================================================
下面是关系配置的各种情况 关系一对多 其实 就是 配置导航属性(如果没有外键,就在EntityTypeConfiguration 指定),如果配置了外键了 就指定外键 其实挺简单
实体类 都包含导航属性 并且多端含有外键 BlogId
此关系按约定发现。 即:
Blog
作为关系中的主体实体被发现,Post
作为依赖实体被发现。Post.BlogId
作为引用主体实体的Blog.Id
主键的依赖实体的外键被发现。 由于Post.BlogId
不可为空,所以发现这一关系是必需的。Blog.Posts
作为集合导航被发现。Post.Blog
作为引用导航被发现。
/// <summary> /// 博客 /// </summary> public class Blog { public Blog() { Posts = new List<Post>(); } public int Id { get; set; } /// <summary> /// 导航属性发布集合 /// </summary> public IEnumerable<Post> Posts { get; set; } } /// <summary> /// 发布 /// </summary> public class Post { public int Id { get; set; } /// <summary> /// 外键 博客Id /// </summary> public int BlogId { get; set; } /// <summary> /// 导航属性Blog /// </summary> public Blog Blog { get; set; } }
实体类中 配置必须有关系
必需的关系可确保每个依赖实体都必须与某个主体实体相关联。 但是,主体实体可以在没有任何依赖实体的情况下始终存在。 也就是说,必需的关系并不表示始终存在至少一个依赖实体。 无论是在 EF 模型,还是在关系数据库中,都没有确保主体实体与特定数量的依赖实体相关联的标准方法。 如果需要,则必须在应用程序(业务)逻辑中实现它。
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder.ToTable("T_Blogs");
builder.HasKey(x=>x.Id);
//博客和发布时一对多 外键博客BlogId 必须存在关系
builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.BlogId).IsRequired();
}
}
生成的迁移文件 查看 关系 是 onDelete: ReferentialAction.Cascade 这是级联关系 删除blog 时候会连相关发布一起删除
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace WebApplication2.Migrations { /// <inheritdoc /> public partial class init : Migration { /// <inheritdoc /> protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.AlterDatabase() .Annotation("MySql:CharSet", "utf8mb4"); migrationBuilder.CreateTable( name: "T_Blogs", columns: table => new { Id = table.Column<int>(type: "int", nullable: false) .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) }, constraints: table => { table.PrimaryKey("PK_T_Blogs", x => x.Id); }) .Annotation("MySql:CharSet", "utf8mb4"); migrationBuilder.CreateTable( name: "Post", columns: table => new { Id = table.Column<int>(type: "int", nullable: false) .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), BlogId = table.Column<int>(type: "int", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Post", x => x.Id); table.ForeignKey( name: "FK_Post_T_Blogs_BlogId", column: x => x.BlogId, principalTable: "T_Blogs", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }) .Annotation("MySql:CharSet", "utf8mb4"); migrationBuilder.CreateIndex( name: "IX_Post_BlogId", table: "Post", column: "BlogId"); } /// <inheritdoc /> protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( name: "Post"); migrationBuilder.DropTable( name: "T_Blogs"); } } }
以下 是 mysql 表设计
上面例子是 外键不为null 下面例子是 外键为null 导航和外键 Blog? Blog int? BlogId 都设置为null
/// <summary>
/// 博客
/// </summary>
public class Blog
{
public Blog()
{
Posts = new List<Post>();
}
public int Id { get; set; }
/// <summary>
/// 导航属性发布集合
/// </summary>
public IEnumerable<Post> Posts { get; set; }
}
/// <summary>
/// 发布
/// </summary>
public class Post
{
public int Id { get; set; }
/// <summary>
/// 外键 博客Id
/// </summary>
public int? BlogId { get; set; }
/// <summary>
/// 导航属性Blog
/// </summary>
public Blog? Blog { get; set; }
}
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder.ToTable("T_Blogs");
builder.HasKey(x=>x.Id);
//博客和发布时一对多 外键博客BlogId 必须存在关系 IsRequired() 默认为true
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.BlogId).IsRequired();
//博客和发布时一对多 外键为null 博客BlogId 必须存在关系 IsRequired(false)
builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.Id).IsRequired(false);
}
}
外键 关系可以看到 迁移文件 没了
/// <inheritdoc />
public partial class init1 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "T_Blogs",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn)
},
constraints: table =>
{
table.PrimaryKey("PK_T_Blogs", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Post",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false),
BlogId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Post", x => x.Id);
table.ForeignKey(
name: "FK_Post_T_Blogs_Id",
column: x => x.Id,
principalTable: "T_Blogs",
principalColumn: "Id");
})
.Annotation("MySql:CharSet", "utf8mb4");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Post");
migrationBuilder.DropTable(
name: "T_Blogs");
}
}
查看mysql 外键的状态改变了 也就是说删除 blog 相关的发布不会被删除
只有导航属性 没有 外键id情况
/// <summary> /// 博客 /// </summary> public class Blog { public Blog() { Posts = new List<Post>(); } public int Id { get; set; } /// <summary> /// 导航属性发布集合 /// </summary> public IEnumerable<Post> Posts { get; set; } } /// <summary> /// 发布 /// </summary> public class Post { public int Id { get; set; } ///// <summary> ///// 外键 博客Id ///// </summary> //public int? BlogId { get; set; } /// <summary> /// 导航属性Blog /// </summary> public Blog Blog { get; set; } }
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder.ToTable("T_Blogs");
builder.HasKey(x=>x.Id);
//博客和发布时一对多 导航属性 Blog 不为null 外键博客BlogId 必须存在关系 IsRequired() 默认为true
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.BlogId).IsRequired();
//博客和发布时一对多 导航属性 Blog 为null 外键为null 博客BlogId 必须存在关系 IsRequired(false)
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.Id).IsRequired(false);
//博客和发布时一对多 只有导航属性 Blog 没有外键 的必须存在关系IsRequired()
builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired();
}
}
迁移文件中查看 配置的外键关系
/// <inheritdoc /> public partial class init1 : Migration { /// <inheritdoc /> protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.AlterDatabase() .Annotation("MySql:CharSet", "utf8mb4"); migrationBuilder.CreateTable( name: "T_Blogs", columns: table => new { Id = table.Column<int>(type: "int", nullable: false) .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) }, constraints: table => { table.PrimaryKey("PK_T_Blogs", x => x.Id); }) .Annotation("MySql:CharSet", "utf8mb4"); migrationBuilder.CreateTable( name: "Post", columns: table => new { Id = table.Column<int>(type: "int", nullable: false) .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), BlogId = table.Column<int>(type: "int", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Post", x => x.Id); table.ForeignKey( name: "FK_Post_T_Blogs_BlogId", column: x => x.BlogId, principalTable: "T_Blogs", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }) .Annotation("MySql:CharSet", "utf8mb4"); migrationBuilder.CreateIndex( name: "IX_Post_BlogId", table: "Post", column: "BlogId"); } /// <inheritdoc /> protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( name: "Post"); migrationBuilder.DropTable( name: "T_Blogs"); } }
只有导航属性 没有 外键id情况 导航属性 可null
/// <summary>
/// 博客
/// </summary>
public class Blog
{
public Blog()
{
Posts = new List<Post>();
}
public int Id { get; set; }
/// <summary>
/// 导航属性发布集合
/// </summary>
public IEnumerable<Post> Posts { get; set; }
}
/// <summary>
/// 发布
/// </summary>
public class Post
{
public int Id { get; set; }
///// <summary>
///// 外键 博客Id
///// </summary>
//public int? BlogId { get; set; }
/// <summary>
/// 导航属性Blog
/// </summary>
public Blog? Blog { get; set; }
}
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder.ToTable("T_Blogs");
builder.HasKey(x=>x.Id);
//博客和发布时一对多 导航属性 Blog 不为null 外键博客BlogId 必须存在关系 IsRequired() 默认为true
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.BlogId).IsRequired();
//博客和发布时一对多 导航属性 Blog 为null 外键为null 博客BlogId 必须存在关系 IsRequired(false)
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.Id).IsRequired(false);
//博客和发布时一对多 只有导航属性 Blog 没有外键 的必须存在关系IsRequired()
// builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired();
//博客和发布时一对多 只有导航属性 Blog 没有外键 的必须存在关系IsRequired(false)
builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired(false);
}
}
/// <inheritdoc />
public partial class init1 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "T_Blogs",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn)
},
constraints: table =>
{
table.PrimaryKey("PK_T_Blogs", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Post",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
BlogId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Post", x => x.Id);
table.ForeignKey(
name: "FK_Post_T_Blogs_BlogId",
column: x => x.BlogId,
principalTable: "T_Blogs",
principalColumn: "Id");
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_Post_BlogId",
table: "Post",
column: "BlogId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Post");
migrationBuilder.DropTable(
name: "T_Blogs");
}
}
没有导航属性 只有外键
{
/// <summary>
/// 博客
/// </summary>
public class Blog
{
public Blog()
{
Posts = new List<Post>();
}
public int Id { get; set; }
/// <summary>
/// 导航属性发布集合
/// </summary>
public IEnumerable<Post> Posts { get; set; }
}
/// <summary>
/// 发布
/// </summary>
public class Post
{
public int Id { get; set; }
///// <summary>
///// 外键 博客Id
///// </summary>
public int BlogId { get; set; }
///// <summary>
///// 导航属性Blog
///// </summary>
// public Blog? Blog { get; set; }
}
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder.ToTable("T_Blogs");
builder.HasKey(x=>x.Id);
//博客和发布时一对多 导航属性 Blog 不为null 外键博客BlogId 必须存在关系 IsRequired() 默认为true
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.BlogId).IsRequired();
//博客和发布时一对多 导航属性 Blog 为null 外键为null 博客BlogId 必须存在关系 IsRequired(false)
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.Id).IsRequired(false);
//博客和发布时一对多 只有导航属性 Blog 没有外键 的必须存在关系IsRequired()
// builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired();
//博客和发布时一对多 只有导航属性 Blog 没有外键 的必须存在关系IsRequired(false)
// builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired(false);
//博客和发布时一对多 没有有导航属性 Blog 只有有外键 的必须存在关系IsRequired()
builder.HasMany(x => x.Posts).WithOne().HasForeignKey(x=>x.BlogId).IsRequired();
}
}
/// <inheritdoc />
public partial class init1 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "T_Blogs",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn)
},
constraints: table =>
{
table.PrimaryKey("PK_T_Blogs", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Post",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
BlogId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Post", x => x.Id);
table.ForeignKey(
name: "FK_Post_T_Blogs_BlogId",
column: x => x.BlogId,
principalTable: "T_Blogs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_Post_BlogId",
table: "Post",
column: "BlogId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Post");
migrationBuilder.DropTable(
name: "T_Blogs");
}
}
没有 导航属性 只有外键
/// <summary>
/// 博客
/// </summary>
public class Blog
{
public Blog()
{
// Posts = new List<Post>();
}
public int Id { get; set; }
///// <summary>
///// 导航属性发布集合
///// </summary>
//public IEnumerable<Post> Posts { get; set; }
}
/// <summary>
/// 发布
/// </summary>
public class Post
{
public int Id { get; set; }
///// <summary>
///// 外键 博客Id
///// </summary>
public int BlogId { get; set; }
///// <summary>
///// 导航属性Blog
///// </summary>
// public Blog? Blog { get; set; }
}
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder.ToTable("T_Blogs");
builder.HasKey(x => x.Id);
//博客和发布时一对多 导航属性 Blog 不为null 外键博客BlogId 必须存在关系 IsRequired() 默认为true
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.BlogId).IsRequired();
//博客和发布时一对多 导航属性 Blog 为null 外键为null 博客BlogId 必须存在关系 IsRequired(false)
//builder.HasMany(x=>x.Posts).WithOne(x=>x.Blog).HasForeignKey(x=>x.Id).IsRequired(false);
//博客和发布时一对多 只有导航属性 Blog 没有外键 的必须存在关系IsRequired()
// builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired();
//博客和发布时一对多 只有导航属性 Blog 没有外键 的必须存在关系IsRequired(false)
// builder.HasMany(x => x.Posts).WithOne(x => x.Blog).HasForeignKey("BlogId").IsRequired(false);
//博客和发布时一对多 Blog有导航属性 Post没有有导航属性 Blog 只有有外键 的必须存在关系IsRequired()
// builder.HasMany(x => x.Posts).WithOne().HasForeignKey(x=>x.BlogId).IsRequired();
//博客和发布时一对多 Blog没有有导航属性 只有有外键 的必须存在关系IsRequired()
builder.HasMany<Post>().WithOne().HasForeignKey(x => x.BlogId).IsRequired();
}
}
/// <inheritdoc />
public partial class init1 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "T_Blogs",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn)
},
constraints: table =>
{
table.PrimaryKey("PK_T_Blogs", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Post",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
BlogId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Post", x => x.Id);
table.ForeignKey(
name: "FK_Post_T_Blogs_BlogId",
column: x => x.BlogId,
principalTable: "T_Blogs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_Post_BlogId",
table: "Post",
column: "BlogId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Post");
migrationBuilder.DropTable(
name: "T_Blogs");
}
}
在没有配置外键得情况下 可以使用 EF.Property<int>(x, "BlogId") == id) 进行查询
/// <summary>
/// 查询
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Blog> FindByIdAsync(int id)
{
//通过阴影属性查询
Blog blog = await _context.Blogs.Include(x =>
x.Posts.Where(x => EF.Property<int>(x, "BlogId") == id)).AsNoTracking().FirstOrDefaultAsync(x => x.Id == id);
return blog;
}