EF Core 如何将实体导航属性映射存储到同一张数据库表
EF Core 实现内嵌类与主实体同表存储配置方案
你之前使用builder.HasOne(x => x.Address)不生效是因为HasOne用于配置两个独立实体的关联关系,默认会映射到两张独立表,与需求不符。
你需要使用EF Core的**拥有实体类型(Owned Entity Type)**特性,该特性默认会将内嵌类的属性映射到主实体所在的同一张表,且字段命名规则默认为导航属性名_内嵌类属性名,完全匹配你需要的Address_Street、Address_ZipCode格式。
配置方式1:Fluent API 配置(推荐)
在你的DbContext的OnModelCreating方法中添加如下配置即可:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>() .OwnsOne(u => u.Address); }
如果需要自定义生成的数据库字段名,可以按照如下方式修改:
modelBuilder.Entity<User>() .OwnsOne(u => u.Address, addrBuilder => { // 自定义Street对应的字段名,不需要自定义的话可以省略这段配置 addrBuilder.Property(a => a.Street).HasColumnName("DeliveryStreet"); addrBuilder.Property(a => a.ZipCode).HasColumnName("DeliveryZipCode"); });
配置方式2:数据注解配置
直接在User类的Address属性上添加[Owned]注解即可,首先需要引入对应的命名空间:
using Microsoft.EntityFrameworkCore;
修改后的实体类如下:
public class User { public int Id { get; set; } public string UserName { get; set; } [Owned] public UserAddress Address { get; set; } } public class UserAddress { public string Street { get; set; } public string ZipCode { get; set; } }
额外注意事项
UserAddress作为拥有实体类型,不需要在DbContext中声明对应的DbSet,也不需要单独配置实体映射- 查询
User时会默认自动加载Address属性,不需要手动调用Include方法,完全符合你代码层面的使用习惯 - 若主实体中存在多个同类型的内嵌属性(比如同时有
HomeAddress、WorkAddress两个UserAddress类型的属性),EF Core会自动生成不同前缀的字段,不会出现命名冲突
内容的提问来源于stack exchange,提问作者Vivendi
相关产品推荐
相关产品推荐

