You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core 5中OwnsMany值对象关系下Update操作不生效问题

EF Core 5 中OwnsMany关联值对象更新失效问题

问题场景

实体与值对象定义

public class User : Entity
{
    public List<Skill> Skills { get; set; }
}

public class Skill : ValueObject
{
    public string Name { get; private set; }
}

实体映射配置

public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder
            .OwnsMany(user => user.Skills);
    }
}

配置后EF会自动生成对应的Skills数据表,结构如下:
Skill表结构

原有更新实现

使用工作单元+仓储模式,仓储层Update方法实现:

public virtual void Update(T entityToUpdate)
{
    _context.Entry(entityToUpdate).State = EntityState.Modified;
}

更新后调用工作单元的Commit方法保存:

public void Commit()
{
    _dbContext.SaveChanges();
}

问题表现

查询User实体时可以正常获取包含Skills在内的所有属性,但执行更新操作时,仅User的非集合属性会被更新,Skills集合的变更始终无法同步到数据库。

已尝试的解决方案及对应问题

  1. 手动配置Skill表的主键、外键
public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder
            .OwnsMany(user => user.Skills, skill =>
            {
                skill.WithOwner().HasForeignKey("UserId");
                skill.Property<int>("Id");
                skill.HasKey("id");
            });
    }
}

修改后问题仍存在,Skills集合仍无法更新。

  1. 改为直接调用DbSet.Update方法更新
public virtual void Update(T entityToUpdate)
{
    _dbSet.Update(entityToUpdate);
}

执行更新时抛出并发异常:Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException : Database operation expected to affect 1 row(s) but actually affected 0 row(s).

注意:Skill为值对象,使用影子Id,推测问题根源与此特性相关。

补充代码说明

以下为完整的仓储、工作单元、上下文实现代码:

基础仓储实现

class BaseRepository<T> : IRepository<T> where T : Entity
{
    private readonly Context _context;
    private readonly DbSet<T> _dbSet;

    public BaseRepository(Context context)
    {
        _context = context;
        _dbSet = context.Set<T>();
    }

    public virtual T GetById(Guid id) => _dbSet.AsNoTracking().FirstOrDefault(x => x.Id == id);

    public virtual void Update(T entityToUpdate)
    {
        _context.Entry(entityToUpdate).State = EntityState.Modified;
    }
}

工作单元实现

public class UnitOfWork : IUnitOfWork
{
    private const int SqlObjectAlreadyExistsErrorNumber = 2627;
    private readonly Context _dbContext;
    private BaseRepository<User> _users;

    public UnitOfWork(Context dbContext)
    {
        _dbContext = dbContext;
    }

    public IRepository<User> Users
    {
        get
        {
            return _users ??= new BaseRepository<User>(_dbContext);
        }
    }

    public void Commit()
    {
        _dbContext.SaveChanges();
    }
}

上下文实现

public class Context : DbContext
{
    public Context(DbContextOptions<DeribeContext> options)
        : base(options)
    {
    }

    public DbSet<User> Users { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(DeribeContext).Assembly);
        base.OnModelCreating(modelBuilder);
    }
}

内容的提问来源于stack exchange,提问作者Quico Llinares Llorens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 18:18:00