EF-Model 用于 many-to-many 交汇点 Table

EF-Model for many-to-many Junction Table

我正在尝试为联结表 OwnerCows.dbo 整理 EF-Model。 有一头 class 牛有一个 Id,一个 class 所有者有一个 Id,我想在只有一个 OwnerCowId、一个 CowId(FK) 和一个 OwnerId 的 OwnerCows-table 中引用它们(FK)。

我得到的错误是: 无法在 'Owner.OwnerCows' 和 'OwnerCow.Owner' 之间创建关系,因为 'Owner.CowOwners' 和 'OwnerCow.Owner' 之间已经存在关系。导航属性只能参与单一关系。

这是否意味着我有一个循环引用?我该如何解决这个问题?

Owner.cs:

public class Owner : EntityBase<Guid>
  {

   public string Name { get; set; }

   [NotMapped]
   public ICollection<Cow> Cows { get; set; }
     = new List<Cow>();

   public virtual List<OwnerCow> CowOwners { get; set; }
   public Cow Cow { get; set; }

   }

Cow.cs:

public class Cow : EntityBase<Guid>
{ 
    [MaxLength(50)]
    public string Name { get; set; }         

    public string Breed { get; set; }
    public string Color {  get; set; }

    public ICollection<Entities.Weight> Weights { get; set; }
      = new List<Weight>();
    public ICollection<Vaccination> Vaccinations { get; set; }
      = new List<Vaccination>();

    [NotMapped]
    public ICollection<Owner> CowOwners { get; set; }
     = new List<Owner>();
    public List<OwnerCow> OwnerCows { get; set; }

}

OwnerCows.cs:

public class OwnerCow 
{
    public Guid OwnerCowId { get; set; }
    public Cow Cow { get; set; }
    public Guid CowId { get; set; }
    public Owner Owner { get; set; }
    public Guid OwnerId { get; set; }
}

Context-class:

    public class DogFaceContext : DbContext
    {
      public DogFaceContext()
      {

      }
      public DogFaceContext(DbContextOptions<DogFaceContext> options)
        : base(options)
      {
        Database.Migrate();          
      }

      //Entity Tables
      public virtual DbSet<Owner> Owners { get; set; }
      public virtual DbSet<Cow> Cows { get; set; }
      public virtual DbSet<Vaccination> Vaccination { get; set; }
      public virtual DbSet<Weight> Weight { get; set; }

      //Junction Tables
      public virtual DbSet<OwnerCow> OwnerCows { get; set; }

      protected override void OnModelCreating(ModelBuilder builder)
      {
        base.OnModelCreating(builder);

        builder.Entity<Cow>().HasMany(x => x.CowOwners).WithOne(x => x.Cow);
        builder.Entity<Owner>().HasMany(u => u.CowOwners).WithOne(X => X.Owner);

        builder.Entity("DogFace.API.Entities.OwnerCow", b =>
        {
          b.HasOne("DogFace.API.Entities.Cow", "Cow")
          .WithMany("OwnerCows")
          .HasForeignKey("CowId")
          .OnDelete(DeleteBehavior.Restrict);

         b.HasOne("DogFace.API.Entities.Owner", "Owner")
         .WithMany("OwnerCows")
         .HasForeignKey("OwnerId")
         .OnDelete(DeleteBehavior.Restrict);
        });
      }
   }

我可以让它与这个设计一起工作吗? EFCore 有可能吗?还有其他建议吗?谢谢!

修复上下文构建器:

  protected override void OnModelCreating(ModelBuilder builder)
  {
    base.OnModelCreating(builder);

    builder.Entity<Cow>().HasMany(x => x.CowOwners).WithOne(x => x.Cow);
    builder.Entity<Owner>().HasMany(u => u.Cows).WithOne(X => X.Owner); // Cows instead of CowOwners

    builder.Entity("DogFace.API.Entities.OwnerCow", b =>
    {
      b.HasOne("DogFace.API.Entities.Cow", "Cow")
      .WithMany("OwnerCows")
      .HasForeignKey("CowId")
      .OnDelete(DeleteBehavior.Restrict);

     b.HasOne("DogFace.API.Entities.Owner", "Owner")
     .WithMany("CowOwners") // CowOwners instead of OwnerCows
     .HasForeignKey("OwnerId")
     .OnDelete(DeleteBehavior.Restrict);
    });
  }

... 或修复 类 中的 属性 个名称:

public class Owner : EntityBase<Guid>
{
    public string Name { get; set; }

    [NotMapped]
    public ICollection<Cow> CowOwners { get; set; } // CowOwners instead of Cows ?
        = new List<Cow>();

    public virtual List<OwnerCow> OwnerCow { get; set; } // OwnerCow instead  of CowOwners ?
    public Cow Cow { get; set; }
}

但不要忘记使用固定的 属性 名称更改 dbcontext 构建器。

您的模型非常复杂并且有一些不必要的关系,例如 Owner.Cows 因为您决定配置多对多 relationship.You 可以使用

获得所有者的奶牛
var owner = new Owner();
List<Cow> cows = owner.OwnerCows.Where(oc => oc.OwnerId == owner.Id)
                       .Select(oc => oc.Cow)
                       .ToList();

1.ToOwnerCows中有OwnerCowId,一个CowId(FK)和一个OwnerId(FK),参考我下面的配置:

public class Owner : EntityBase<Guid>
{
    public string Name { get; set; }   

    public virtual List<OwnerCow> OwnerCows { get; set; }
}

public class Cow : EntityBase<Guid>
{
    [MaxLength(50)]
    public string Name { get; set; }
    public string Breed { get; set; }
    public string Color { get; set; }
    public ICollection<Entities.Weight> Weights { get; set; } = new List<Weight>();
    public ICollection<Vaccination> Vaccinations { get; set; }= new List<Vaccination>();

    public List<OwnerCow> OwnerCows { get; set; }

}

public class OwnerCow
{
    [Key]
    public Guid OwnerCowId { get; set; }
    public Cow Cow { get; set; }
    public Guid CowId { get; set; }
    public Owner Owner { get; set; }
    public Guid OwnerId { get; set; }
}

数据库上下文:

protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<OwnerCow>()
                .HasOne(oc => oc.Cow)
                .WithMany(c => c.OwnerCows)
                .HasForeignKey(oc => oc.CowId);
        builder.Entity<OwnerCow>()
            .HasOne(oc => oc.Owner)
            .WithMany(o => o.OwnerCows)
            .HasForeignKey(oc => oc.OwnerId);

    }
}

在这种情况下,您的 OwnerCowId id 是您 OwnerCows table 的主键,这是不合理的,它可能具有与 OwnerCows 相同的 CowId、OwnerId 记录。

2.Usually,join table 的主键是一个包含两个外键值的组合键,我建议你可以为你的 OwnerCow 使用组合键:

public class OwnerCow
{
    public Cow Cow { get; set; }
    public Guid CowId { get; set; }
    public Owner Owner { get; set; }
    public Guid OwnerId { get; set; }
}

数据库上下文:

protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);


        builder.Entity<OwnerCow>()
               .HasKey(oc => new { oc.OwnerId, oc.CowId });
        builder.Entity<OwnerCow>()
                .HasOne(oc => oc.Cow)
                .WithMany(c => c.OwnerCows)
                .HasForeignKey(oc => oc.CowId);
        builder.Entity<OwnerCow>()
            .HasOne(oc => oc.Owner)
            .WithMany(o => o.OwnerCows)
            .HasForeignKey(oc => oc.OwnerId);

    }
}

参考https://www.learnentityframeworkcore.com/configuration/many-to-many-relationship-configuration