【问题标题】:Self referencing table with Entity Framework Core 5使用 Entity Framework Core 5 的自引用表
【发布时间】:2021-01-29 04:43:24
【问题描述】:

我的应用中有一个自引用实体。与其他包类型具有依赖关系(作为列表)的包类型。我正在尝试使用模型构建器设计所需的中间表。不幸的是,我无法正确填写密钥。

System.InvalidOperationException: '无法跟踪'PackageDependency (Dictionary)' 类型的实体,因为它的主键属性'DependencyId' 为空。'

    public class PackageType
    {
        [Key]
        public String Tag { get; set; }

        public virtual List<PackageType> Dependencies { get; set; } = new List<PackageType>();
    }

数据库上下文:

 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<PackageType>()
                .HasMany(p => p.Dependencies)
                .WithMany(p => p.Dependencies)
                .UsingEntity<Dictionary<string, object>>(
                    "PackageDependency",
                    j => j
                        .HasOne<PackageType>()
                        .WithMany()
                        .HasForeignKey("PackageId")
                        .HasConstraintName("FK_PackageDependency_PackageId")
                        .OnDelete(DeleteBehavior.Cascade),
                    j => j
                        .HasOne<PackageType>()
                        .WithMany()
                        .HasForeignKey("DependencyId")
                        .HasConstraintName("FK_PackageDependency_DependencyId")
                        .OnDelete(DeleteBehavior.ClientCascade),
                    e => e.HasKey("PackageId", "DependencyId"));
        }

有人给我提示吗?

非常感谢!

【问题讨论】:

    标签: .net-core entity-framework-core


    【解决方案1】:

    我很惊讶 EF Core 竟然允许这样做

    .HasMany(p => p.Dependencies)
    .WithMany(p => p.Dependencies)
    

    (对关系的双方使用同一个集合)而不报告错误。

    Many-to-many 需要 2 个集合导航属性 - 关系的每一侧一个。因此,即使这是自引用关系,它仍然需要 2 个单独的集合导航属性绑定到相应的连接实体 FK。例如

    public virtual List<PackageType> ChildDependencies { get; set; } = new List<PackageType>();
    public virtual List<PackageType> ParentDependencies { get; set; } = new List<PackageType>();
    

    .HasMany(p => p.ChildDependencies) // -> j.PackageId
    .WithMany(p => p.ParentDependencies) // -> j.DependencyId
    

    【讨论】:

      【解决方案2】:

      你需要两个参考,一个是向上的,另一个是向下的:

      public class PackageType
      {
          [Key]
          public String Tag { get; set; }
      
          public ICollection<PackageDependency> Dependents { get; set; }
          public ICollection<PackageDependency> Pendents { get; set; }
      }
      
      public class PackageDependency
      {
          public string DependentTag { get; set; }
          public PackageType Dependend { get; set }
          public string PendentTag { get; set; }
          public PackageType Pendend { get; set; }
      }
      
      
      protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
          modelBuilder.Entity<PackageDependency>()
                  .HasKey(r => new { r.DependentTag, r.PendentTag });
          modelBuilder.Entity<PackageDependency>()
              .HasOne(r => r.Pendend)
              .WithMany(p => p.Dependents)
              .IsRequired()
              .OnDelete(DeleteBehavior.NoAction);
          modelBuilder.Entity<PackageDependency>()
              .HasOne(r => r.Dependend)
              .WithMany(d => d.Pendents)
              .IsRequired()
              .OnDelete(DeleteBehavior.NoAction);
      }
      

      【讨论】:

      • 嗨。谢谢您的帮助。我标记了另一个解决方案,因为它实施起来更快并且更适合我的需求。还是谢谢!
      猜你喜欢
      • 2017-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多