EF Core Code First复杂类型迁移报错:需定义ID的解决方案咨询
解决EF Core复杂类型集合(OwnsMany)迁移时的Id必填问题
这个问题我之前也碰到过,本质是EF Core处理OwnsMany映射的复杂类型集合时,需要为子对象生成主键用于数据库关联,但你的Address类的不可变设计(私有无参构造)加上缺少显式键配置,导致EF Core无法自动完成映射。下面给你两种可行的解决办法:
方案一:调整Address类的构造函数访问权限
EF Core需要能够实例化你的复杂类型对象来进行追踪和映射,所以可以把Address的无参构造改为internal或者public(不需要对外暴露,只要EF Core能访问到就行),同时保留带参数的构造函数保证业务逻辑的不可变性:
public class Address { public string Street { get; private set; } // 改为internal,让EF Core可以实例化对象 internal Address() { } public Address(string street) { Street = street; } }
另外还要注意把MyContext中的Persons DbSet改为public,否则EF Core无法正确识别实体集:
public class MyContext : DbContext { public MyContext() { } // 改为public public DbSet<Person> Persons { get; set; } // ... 其他配置代码不变 }
修改后重新执行add-migration initialmigration,EF Core会自动为Addresses集合生成一个阴影属性主键(比如Addresses_Id),同时关联Person的Id作为外键,迁移就能正常生成了。
方案二:显式配置阴影键并绑定构造函数
如果你想严格保持Address的无参构造为私有,可以在OnModelCreating中显式配置阴影属性作为Address的主键,并且告诉EF Core使用带参数的构造函数来创建实例:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Person>().Property(k => k.Id).ValueGeneratedOnAdd(); modelBuilder.Entity<Person>(entity => { entity.OwnsMany(m => m.Addresses, address => { // 显式定义阴影属性作为Address的主键,自动生成值 address.Property<int>("AddressId").ValueGeneratedOnAdd(); address.Property(x => x.Street).HasColumnName("Street"); // 告诉EF Core使用带string参数的构造函数创建Address实例 address.HasConstructor(typeof(string)); }); }); }
这种方式不需要修改Address类的构造权限,EF Core会用你指定的构造函数创建对象,同时用AddressId作为子表的主键,和Person的Id组成关联关系,迁移命令就能正常执行了。
内容的提问来源于stack exchange,提问作者user3661407
相关产品推荐
相关产品推荐

