我有一个场景user可以上传多个photos(一对多)。这user还可以有默认照片(一对一)。然而,我实体框架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”忽略此属性。
UPDATE:
Adding [InverseProperty("Photos")]
到导航属性Owner在文件模型中似乎正在工作。我不确定这是否是正确的方法?
In this image File=Photo; Uploader=Owner (to be comparable with the above model).
更新2:
我确认@Ivan 在评论中所说的,通过 DataAnnotation 方法,我在两个方向上得到一对多,而不是一对多和一对一。该图显示了使用生成的数据库InverseProperty
(to实体之间的连接显示双向一对多关系):
在此图像中 File=Photo; Uploader=Owner(与上述模型相当)。
使用 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
) 关系,必须在两个主键或两个候选键之间建立关系。 (查看这篇博文 https://gldraphael.com/blog/notes-on-database-relationships/有关这方面的更多信息。)
EF 目前无法通过注释设置候选键(也称为唯一键或备用键),因此这是您唯一的选择。在 Microsoft Docs 中查看 EF 文档:一对一的关系 https://learn.microsoft.com/en-us/ef/core/modeling/relationships#other-relationship-patterns
Update:早期的代码会自动生成一个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
。这只是在此类情况下明确关系的一种方式。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)