Entity Framework Core调用DbSet.Add后Owned Type属性丢失值
问题现象
使用Entity Framework Core开发项目时,遇到Owned Type相关异常:
- 创建新的MainEntity并通过
AddAsync添加到上下文后,ThirdEntity中的MyOwnedType属性会立即变为null,但SecondEntity中的该属性不受影响,且调用AddAsync前该属性有值。 - 尝试先将ThirdEntity直接添加到DbSet时,它的MyOwnedType值不会丢失,但添加MainEntity到上下文后,ThirdEntity的MyOwnedType属性全部变为null。
- 调用
SaveChanges时抛出异常:
System.InvalidOperationException: 'Cannot save instance of 'MainEntity.MyOwnedTypeStart#MyOwnedType' because it is an owned entity without any reference to its owner. Owned entities can only be saved as part of an aggregate also including the owner entity.'
- 添加日志后出现以下警告:
warn: 30/05/2024 11:52:30.440 CoreEventId.DuplicateDependentEntityTypeInstanceWarning[10001] (Microsoft.EntityFrameworkCore.Update)
The same entity is being tracked as different entity types 'ThirdEntity.MyOwnedType#MyOwnedType' and 'MainEntity.CompetenciaStart#MyOwnedType' with defining navigations. If a property value changes, it will result in two store changes, which might not be the desired outcome.
实体结构代码
class MainEntity { public Guid Id { get; set; } public virtual List<SecondEntity>? Seconds { get; set; } public MyOwnedType MyOwnedTypeStart { get; set; } = null!; public MyOwnedType MyOwnedTypeEnd { get; set; } = null!; } class SecondEntity { public Guid Id { get; set; } public Guid MainEntityId { get; set; } public virtual MainEntity? MainEntity { get; set; } public virtual List<ThirdEntity>? Third { get; set; } public MyOwnedType MyOwnedType { get; set; } = null!; } class ThirdEntity { public Guid Id { get; set; } public Guid SecondEntityId { get; set; } public virtual SecondEntity? SecondEntity { get; set; } public MyOwnedType MyOwnedType { get; set; } = null!; } public record MyOwnedType { public EMonth Month { get; init; } public ushort Year { get; init; } } public enum EMonth { January = 1, February = 2, March = 3, April = 4, May = 5, June = 6, July = 7, August = 8, September = 9, October = 10, November = 11, December = 12, ExtraMonth = 13 }
添加实体代码
public virtual Task AddAsync(MainEntity entity) { // ... some code here ... return dbSet.AddAsync(entity).AsTask(); }
Owned Type配置代码
builder.OwnsOne(o => o.Competencia, sa => { const string monthColumnName = "EMonth"; const string yearColumnName = "Year"; sa.Property(p => p.Month).HasColumnName(monthColumnName); sa.Property(p => p.Year).HasColumnName(yearColumnName); });
问题分析与解决思路
- 重复跟踪警告的核心原因:EF Core将同一个MyOwnedType实例同时跟踪为不同的拥有实体类型(如
ThirdEntity.MyOwnedType和MainEntity.MyOwnedTypeStart)。因为EF Core要求每个Owned Type实例必须属于唯一的所有者,若在多个实体间复用同一个MyOwnedType实例,会触发跟踪冲突,最终导致属性被置空。 - 具体解决步骤:
- 确保每个实体的MyOwnedType属性都是独立实例,不要在多个实体间复用同一个对象。比如创建ThirdEntity时,要新建
new MyOwnedType { ... },而非引用其他实体的实例。 - 检查Owned Type配置的完整性:当前配置仅针对
Competencia属性(推测是MyOwnedTypeStart或MyOwnedTypeEnd的笔误),需确保MainEntity的MyOwnedTypeStart、MyOwnedTypeEnd,SecondEntity和ThirdEntity的MyOwnedType都通过OwnsOne完成正确配置。 - 避免手动单独添加ThirdEntity到DbSet,而是通过
MainEntity.Seconds[x].Third导航属性添加子实体,让EF Core自动维护所有者与Owned Type的关联关系。
- 确保每个实体的MyOwnedType属性都是独立实例,不要在多个实体间复用同一个对象。比如创建ThirdEntity时,要新建
内容的提问来源于stack exchange,提问作者Joao Paulo Salles Beraldo

