【问题标题】:How can I include two relational properties of the same type?如何包含两个相同类型的关系属性?
【发布时间】:2020-04-08 12:11:24
【问题描述】:

我有一个 ApplicationUser 模型:

public class ApplicationUser : IdentityUser
{
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    public List<Project> Projects { get; set; }
}

...和一个项目模型:

public class Project
{
    public int Id { get; set; }
    public int? ParentProjectId { get; set; }

    [Required]
    public string ProjectCreatorId { get; set; }

    [Required]
    public string ProjectOwnerId { get; set; }

    public string Title { get; set; }
    public DateTime Created { get; set; }

    public ApplicationUser ProjectCreator { get; set; }
    public ApplicationUser ProjectOwner { get; set; }
    public Project ParentProject { get; set; }
    public virtual List<Project> ChildProjects { get; set; }
}

OnModelCreating(),我试过这个:

base.OnModelCreating(modelBuilder);

modelBuilder.Entity<Project>()
    .HasMany(c => c.ChildProjects)
    .WithOne(p => p.ParentProject)
    .HasForeignKey(p => p.ParentProjectId);

modelBuilder.Entity<ApplicationUser>()
    .HasMany(p => p.Projects)
    .WithOne(o => o.ProjectOwner)
    .HasForeignKey(po => po.ProjectOwnerId);

modelBuilder.Entity<ApplicationUser>()
    .HasMany(p => p.Projects)
    .WithOne(c => c.ProjectCreator)
    .HasForeignKey(pc => pc.ProjectCreatorId);

但是在创建数据库时,我得到了

无法在“ApplicationUser.Projects”和“Project.ProjectCreator”之间创建关系,因为“ApplicationUser.Projects”和“Project.ProjectOwner”之间已经存在关系。导航属性只能参与单个关系。

我尝试了this old question 的解决方案,但无法使它们中的任何一个起作用。

是否有另一种方法可以同时跟踪Project 的创建者和所有者,并能够在查询中同时.Include() 他们?

【问题讨论】:

  • 您需要ApplicationUser 中的两个导航属性,例如OwnedProjectsCreatedProjects,因为您不能针对不同的关系使用两次Projects
  • 或者,您可以在它们之间放置一个包含列的表,以指定用户是否拥有和/或创建项目。这样一来,您就不会有可能重复的项目链接到同一用户两次。
  • @juharr 我想我会尝试链接表的方法。谢谢你提醒我他们的存在! ;) 我稍后会发布更新。

标签: c# asp.net-core entity-framework-core relational-database code-first


【解决方案1】:

不要使用不同的绑定,而是使用单个绑定

modelBuilder.Entity<ApplicationUser>()
.HasMany(p => p.Projects)
.WithOne(o => o.ProjectOwner)
.HasForeignKey(po => po.ProjectOwnerId);
.WithOne(c => c.ProjectCreator)
.HasForeignKey(pc => pc.ProjectCreatorId);

【讨论】:

    【解决方案2】:

    我选择了这个解决方案:

    如 cmets 中所述,ApplicationUser 需要两个 List&lt;Project&gt;-properties:

    public List<Project> CreatedProjects { get; set; }
    public List<Project> OwnedProjects { get; set; }
    

    然后,在OnModelCreating()

    modelBuilder.Entity<Project>()
        .HasOne(g => g.ProjectCreator)
        .WithMany(t => t.CreatedProjects)
        .HasForeignKey(t => t.ProjectCreatorId)
        .HasPrincipalKey(t => t.Id);
    modelBuilder.Entity<Project>()
        .HasOne(g => g.ProjectOwner)
        .WithMany(t => t.OwnedProjects)
        .HasForeignKey(t => t.ProjectOwnerId).OnDelete(DeleteBehavior.NoAction)
        .HasPrincipalKey(t => t.Id);
    

    现在我可以同时包含创作者和所有者。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-17
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      相关资源
      最近更新 更多