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

EF Core JSON列自引用拥有类型迁移报错求助

解决EF Core将实体保存到SQL Server JSON列时的迁移报错问题

问题描述

尝试把嵌套实体模型存入SQL Server的JSON列,运行Add-Migration version命令时触发以下错误:

无法确定“VersionItemsEntity.Children#VersionItemsEntity.Data”与“VersionItemsDataEntity”之间关系的所有者,因为这两种类型都已标记为拥有类型。请手动配置所有权,或使用[NotMapped]特性或在OnModelCreating中使用“EntityTypeBuilder.Ignore”忽略相应的导航属性。

相关实体模型与原配置代码如下:

实体模型代码

public class VersionEntity 
{
    public VersionEntity()
    {
    }

    public VersionItemEntity Items { get; set; }
    public long ProjectId { get; set; }
    public int TenantId { get; set; }
}

public class VersionItemEntity
{
    public List<VersionItemsEntity> VersionItems { get; set; }
}

public class VersionItemsEntity
{
    public VersionItemsEntity()
    {
    }

    public string Key { get; set; }
    public string Label { get; set; }
    public VersionItemsDataEntity Data { get; set; }
    public string Icon { get; set; }
    public List<VersionItemsEntity> Children { get; set; } = new();
}

public class VersionItemsDataEntity
{
    public string Title { get; set; }
    public int? Order { get; set; }
    public DateTime? ReleaseDate { get; set; }
}

原OnModelCreating配置

private void VersionModelCreating(ModelBuilder modelBuilder)
{
        modelBuilder.Ignore<VersionItemsDataEntity>();
        modelBuilder.Entity<VersionEntity>().OwnsOne(
          version => version.Items, ownedNavigationBuilder =>
          {
              ownedNavigationBuilder.OwnsMany(
              metadata => metadata.VersionItems, ownedOwnedNavigationBuilder =>
              {
                  ownedOwnedNavigationBuilder.OwnsMany(vi => vi.Children);
                  ownedOwnedNavigationBuilder.OwnsOne(vi => vi.Data);
                  ownedNavigationBuilder.ToJson();
              }
              );
          });
        modelBuilder.Entity<VersionEntity>().Property(o => o.Id).UseIdentityColumn(Back_SoftConsts.InitialValue);
    }

问题根源

  1. 错误调用modelBuilder.Ignore<VersionItemsDataEntity>(),但实体中需要用该类型作为导航属性,忽略操作导致EF无法识别其所有权关系。
  2. ToJson()方法位置错误,应在最上层的拥有类型(Items)配置中调用,而非嵌套在OwnsMany的层级里。
  3. 嵌套的Children集合中的Data属性未明确配置所有权,EF无法解析该关系。

解决方案

修改VersionModelCreating方法,调整配置层级,明确所有嵌套拥有类型的关系,移除错误的Ignore调用:

private void VersionModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<VersionEntity>(entity =>
    {
        // 配置Id自增规则
        entity.Property(o => o.Id).UseIdentityColumn(Back_SoftConsts.InitialValue);

        // 配置Items为拥有类型,并转为JSON列存储
        entity.OwnsOne(version => version.Items, ownedNavigationBuilder =>
        {
            ownedNavigationBuilder.ToJson(); // 将整个Items对象序列化为JSON

            // 配置VersionItems集合
            ownedNavigationBuilder.OwnsMany(metadata => metadata.VersionItems, versionItemsBuilder =>
            {
                // 明确当前VersionItems的Data属性所有权
                versionItemsBuilder.OwnsOne(vi => vi.Data);

                // 递归配置Children集合
                versionItemsBuilder.OwnsMany(vi => vi.Children, childrenBuilder =>
                {
                    // 明确Children中Data属性的所有权
                    childrenBuilder.OwnsOne(c => c.Data);
                });
            });
        });
    });
}

说明

  • 移除modelBuilder.Ignore<VersionItemsDataEntity>(),因为VersionItemsEntity依赖该类型作为拥有属性,不能忽略。
  • 将ToJson()放在Items的拥有类型配置中,确保整个Items对象(含所有嵌套集合与属性)都被序列化为JSON存入SQL Server。
  • 对Children内部的Data属性显式调用OwnsOne,明确所有权关系,解决EF的识别问题。

修改完成后重新运行Add-Migration version即可正常生成迁移文件。

内容的提问来源于stack exchange,提问作者Iman Bahrampour

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:35:04