我正在按照本教程使用 EF Core 1.1 实现我的友谊系统:http://www.codedodle.com/2014/12/social-network-friends-database.html
友谊.cs
public class Friendship
{
public Guid ApplicationUserId { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public Guid FriendId { get; set; }
public ApplicationUser Friend { get; set; }
public StatusCode Status { get; set; }
public Guid ActionUserId { get; set; }
public ApplicationUser ActionUser { get; set; }
public byte[] Timestamp { get; set; }
}
public enum StatusCode
{
Pending = 0,
Accepted = 1,
Declined = 2,
Blocked = 3
}
ApplicationUser.cs
public class ApplicationUser : IdentityUser<Guid>
{
...
public ICollection<Friendship> FriendRequestsMade { get; set; }
public ICollection<Friendship> FriendRequestsAccepted { get; set; }
public byte[] Timestamp { get; set; }
}
MyDbContext.cs
public class SocialCircleContext : IdentityDbContext<ApplicationUser, Role, Guid>
{
builder.Entity<Friendship>()
.HasIndex(x => new { x.ApplicationUserId, x.FriendId })
.IsUnique();
builder.Entity<Friendship>()
.HasOne(x => x.ApplicationUser)
.WithMany(y => y.FriendRequestsMade)
.HasForeignKey(x => x.ApplicationUserId).OnDelete(DeleteBehavior.Restrict);
builder.Entity<Friendship>()
.HasOne(x => x.Friend)
.WithMany(y => y.FriendRequestsAccepted)
.HasForeignKey(x => x.FriendId);
}
Add-Migration InitialMigration 的结果
Unable to determine the relationship represented by navigation property 'Friendship.ActionUser' of type 'ApplicationUser'. Either manually configure the relationship, or ignore this property from the model.
此外,由于 EF Core 发展迅速,我发现了很多不同的方法来实现这一点。我不确定我如何实现自引用多对多关系,有人可以给我一些建议吗?
- 如何定义 Friendship.ActionUser 和 ApplicationUser 之间的关系?
- 关于实现这种自引用多对多关系的正确方法有何建议? EF Core 发展很快,我在网上找到了很多不同的方法,但它们似乎已经过时了
谢谢! :)
最佳答案
理想情况下,一旦关系发现中的歧义得到解决,EF 应该按照约定创建其余的关系,但由于错误而没有发生。 (归档 Bug )
您的模型类对于您尝试做的事情是正确的。要使 EF 成功构建模型,需要填补的缺失部分很少。
首先,让我们解决您看到的异常。
您的 ApplicationUser
类有 2 个指向 Friendship
的集合导航。 Friendship
类有 3 个引用导航指向 ApplicationUser
。虽然 EF Core 在按照约定创建关系方面做得很好,但在这种情况下,它不知道如何创建导航-反向导航对。因此需要通过注释/流畅的 API 进行用户输入。在您的情况下,您正在使用流畅的 API 创建 2 个关系,每边使用 2 个导航。这留给我们的只有导航 Friendship.ActionUser
而没有任何关系。此时,EF Core 对如何从中创建关系没有任何困惑,但由于错误,它没有这样做。这意味着您必须使用 Fluent API 手动配置此关系。
builder.Entity<Friendship>().HasOne(e => e.ActionUser).WithOne().HasForeignKey<Friendship>(e => e.ActionUserId);
这将创建一对一的关系。您可以使用 HasOne(...).WithMany()
来创建一对多关系。
这将使您克服上述错误。现在您将看到另一个错误,因为类 Friendship
没有定义主键。虽然文章说创建唯一索引,但对于多对多连接表,连接表配置有复合PK,以便它可以表示唯一连接。因此,您应该使用以下代码,而不是像上面那样调用 HasIndex
。
builder.Entity<Friendship>().HasKey(e => new { e.ApplicationUserId, e.FriendId });
在上面的代码之后,您可以删除 HasIndex
调用,因为 PK 始终是唯一的,并且大多数数据库都为 PK 定义了索引。
通过上述更改,您的模型应该可以正常工作。
其他:由于 Friendship.ActionUser
定义的关系对于一对一或一对多来说有些模糊,也许它根本不应该是关系。 ActionUserId 应该采用 ApplicationUserId
或 FriendId
的值之一,您可以通过选择其中一个导航轻松访问 ActionUser。您可以在 EF 中创建 ActionUser [NotMapped]
并根据 ActionUserId
使用返回的值 ApplicationUser/Friend
进行计算。尽管这些是设计选择。没有正确或错误的方法。无论哪种方式最有意义并且对您的消费方式帮助最大,都应该使用它。
关于c# - 如何使用 Entity Framework Core 1.1 实现自引用多对多关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44572936/