【问题标题】:How to define multiple relationships between two entities?如何定义两个实体之间的多重关系?
【发布时间】:2017-12-09 11:56:00
【问题描述】:

我有一个场景,用户可以上传多张照片(一对多)。 用户还可以拥有默认照片(一对一)。但是,我的实体框架core 2.0告诉我使用以下代码时他无法识别关系:

public class User
{
    public Guid Id { get; set; }

    public ICollection<Photo> Photos{ get; set; }

    public Photo DefaultPhoto { get; set; }
    [ForeignKey("DefaultPhoto")]
    public Guid DefaultPhotoId { get; set; }
}

public class Photo
{
    public Guid Id { get; set; }

    public User Owner { get; set; }
}

我怎样才能实现这些多重关系?

EF-Core 显示错误:

System.InvalidOperationException: '无法确定由'User' 类型的导航属性'Photo.Owner' 表示的关系。手动配置关系,或使用“[NotMapped]”属性或使用“OnModelCreating”中的“EntityTypeBuilder.Ignore”忽略此属性。

更新:

[InverseProperty("Photos")] 添加到文件模型中的导航属性Owner 似乎有效。我不确定这是否正确?

在这张图片中 File=Photo; Uploader=Owner(与上述模型相媲美)。

更新 2:

我确认@Ivan 在 cmets 中所说的,通过 DataAnnotation 方法,我在两个方向上得到一对多,而不是一对多和一对一。下图是使用InverseProperty生成的数据库(to实体之间的连接是双向的一对多关系):

在这张图片中 File=Photo; Uploader=Owner(与上述模型相媲美)。

【问题讨论】:

  • 这个属性告诉另一个类的哪个属性是导航属性的“另一端”。因此,通过使用 [InverseProperty("Owner")]` 标记 Photos,您可以知道 User 类中导航属性 Photos 的另一端是 Photo 类中的属性 Owner。同样可以反过来做。如果你用[InverseProperty("Photos")] 标记Owner - 你也在做同样的事情。为什么它以一种方式起作用,而对你却不起作用——我不确定。
  • 我想是的。当我从您的问题中的模型生成数据库时 - 其中一个(OwnerId)被声明为可为空。我想知道当您尝试插入当前数据库时会发生什么。
  • InverseProperty 只解决了一半的问题——正确关联定义导航属性的一对多关系。然而,按照惯例,第二种关系是一对多,而不是所希望的一对一。忘记数据注释,流畅的配置是必须的。
  • 这样 - 默认情况下,User 中的 Photo DefaultPhoto 的倒数类似于 Photo 中的 ICollection&lt;User&gt; DefaultPhotoUsers,或者换句话说 - 一对多。无法使用数据注释将其配置为一对一,因此您应该使用流畅的 API(如@gldraphael 答案)。
  • 没错。

标签: c# .net entity-framework asp.net-core entity-framework-core


【解决方案1】:

使用 Fluent API 建立一对一的关系:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // Establish a one to one relationship with the
    // User as the dependent End
    modelBuilder.Entity<User>()
        .HasOne(u => u.DefaultPhoto)
        .WithOne(p => p.Owner)
        .HasForeignKey<User>(u => u.DefaultPhotoId);
}

要使关系成为一对一 (1:0..1) 关系,必须在两个主键或两个候选键之间建立关系。 (查看this blog post 了解更多信息。)

EF 目前无法通过注释设置候选键(也称为唯一键或备用键),因此这是您唯一的选择。在 Microsoft Docs 上查看 EF 文档:One to One relationships


更新:较早的代码会自动生成UserId 列并正确设置关系。我已将 OwnerId 字段添加到 Photo 实体以手动设置关系,就像您想要的那样:

public class User
{
    public Guid Id { get; set; }

    [InverseProperty("Owner")]
    public ICollection<Photo> Photos{ get; set; }

    public Photo DefaultPhoto { get; set; }
    public Guid DefaultPhotoId { get; set; }
}

public class Photo
{
    public Guid Id { get; set; }

    public Guid OwnerId { get; set; }
    public User Owner { get; set; }
}

public class MyDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Photo> Photos { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // You may use this instead of the inverse property
        // // The One to Many relationship between
        // // User.Id (Principal End) and Photo.OwnerId
        // modelBuilder.Entity<Photo>()
        //     .HasOne(p => p.Owner)
        //     .WithMany(u => u.Photos)
        //     .HasForeignKey(p => p.OwnerId);

        // Establishes 1:0..1 relationship between
        // Photo.Id (Principal End) and User.DefaultPhoto (Dependent end)
        modelBuilder.Entity<User>()
            .HasOne(u => u.DefaultPhoto)
            .WithOne() // we leave this empty because it doesn't correspond to a navigation property in the Photos table
            .HasForeignKey<User>(u => u.DefaultPhotoId);
    }
}

诀窍在于确定关系(尤其是主端和从属端)以及确定哪些关系需要导航属性。

需要 Inverse 属性,因为 EF 不知道要映射到 Photo.Owner 的属性。这只是在此类情况下明确关系的一种方式。

【讨论】:

  • 我正在尝试这个,但如果我将public Guid OwnerId { get; set; } 添加到文件实体会怎样? (我已经尝试添加它但没有成功,甚至定义了键)。
  • @MohammedNoureldin 设法让它工作还是你想让我更新答案?
  • 在 Evk 的帮助下,我得到了它的工作,但 我仍然不明白为什么它工作。您可以更新答案,以便分享知识。谢谢。
  • @MohammedNoureldin 我已经更新了。如果您有任何问题,请告诉我。当我开始使用 EF 时,这是一个主要的挫败感。但是一旦你得到这个,它就是小菜一碟。
  • @MohammedNoureldin EF 约定首先建立了一对多关系。该代码仅适用于 1:0..1 关系。每当 EF 无法弄清楚时,它就会抛出一个错误,这就是为什么您首先在问题中看到错误的原因。
猜你喜欢
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 1970-01-01
相关资源
最近更新 更多