0

我正在尝试为连接表 OwnerCows.dbo 理顺 EF 模型。有一个带有 Id 的类 Cow,一个带有 Id 的类 Owner,我想在只有 OwnerCowId、CowId(FK) 和 OwnerId(FK) 的 OwnerCows 表中引用它们。

我得到的错误是:无法在'Owner.OwnerCows'和'OwnerCow.Owner'之间创建关系,因为'Owner.CowOwners'和'OwnerCow.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; }

   }

牛.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; }
}

上下文类:

    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);
        });
      }
   }

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

4

2 回答 2

2

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

var owner = new Owner();
List<Cow> cows = owner.OwnerCows.Where(oc => oc.OwnerId == owner.Id)
                       .Select(oc => oc.Cow)
                       .ToList();

1.要在 OwnerCows 中有 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);

    }
}

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

2.通常,连接表的主键是包含两个外键值的复合键,我建议您可以使用复合键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

于 2019-09-19T07:09:27.500 回答
1

修复上下文构建器:

  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 builder。

于 2019-09-18T08:10:29.263 回答