如何使用EF Core5和Fluent API配置类似于Twitter追随者和追随者类型的关系?我尝试了各种不同的方法来配置它,唯一能让它正常工作的方法是忽略用户实体上的导航属性。我目前正在将我的代码从EF Core2.1迁移到5。下面的配置在前面起作用。(不确定是否配置错误)
public class User
{
public long Id { get; set; }
public string Name { get; set; }
public ICollection<UserFollower> Followers { get; set; }
public ICollection<UserFollower> Following { get; set; }
}
public class UserFollower
{
public long UserId { get; set; }
public User User { get; set; }
public long FollowedById { get; set; }
public User FollowedBy { get; set; }
}
public class UserFollowerConfiguration : IEntityTypeConfiguration<UserFollower>
{
public void Configure(EntityTypeBuilder<UserFollower> builder)
{
builder.HasKey(p => new { p.UserId, p.FollowedById });
builder.HasOne(p => p.User)
.WithMany(i => i.Followers)
.HasForeignKey(i => i.UserId);
builder.HasOne(p => p.FollowedBy)
.WithMany(i => i.Following)
.HasForeignKey(i => i.FollowedById);
}
}
此配置在保存到数据库时引发错误。
SqlException: Violation of PRIMARY KEY constraint 'PK_UserFollower'.
Cannot insert duplicate key in object 'dbo.UserFollower'. The duplicate key value is (111, 111).
即使在尝试直接添加到DbContext并对其调用saveChanges()
时也是如此。
context.add(new UserFollower(){UserId=222,FollowedById=111});
这样的关系映射到EF Core 5的推荐方式是什么?请注意,我确实需要访问UserFollowers表,而不需要查看用户的导航属性。
试着像这样配置它。
builder.Entity<User>().HasMany(s => s.Followers)
.WithOne(f => f.FollowedBy);
builder.Entity<User>().HasMany(s => s.Following)
.WithOne(f => f.);
此外,userfollower
表缺少PK,我不知道是否在某个地方生成了Id。如果不是,可能这就是它试图错误地使用FollowedbyID
作为键的原因,但是为userfollower
表定义了一个Id,请参阅。
public class UserFollower
{
public long Id {get;set;}
public long UserId { get; set; }
public User User { get; set; }
public long FollowedById { get; set; }
public User FollowedBy { get; set; }
}
即使这样做有效,我也会建议您改变模型的结构,对于您描述的twitter需求来说,它看起来是模棱两可的。如果查询userfollowers
var userFollowers = _context.UserFollowers.ToList();
对于列表中的每个结果,我没有办法告诉用户是在跟踪还是被跟踪。你可以把你的模型换成这些;
public class User
{
public long Id { get; set; }
public string Name { get; set; }
public ICollection<UserFollower> Followers { get; set; }
public ICollection<UserFollowing> Following { get; set; }
}
public class UserFollower
{
public long UserId { get; set; }
public User User { get; set; }
public long UserFollowingMeId { get; set; }
public User UserFollowingMe { get; set; }
}
public class UserFollowing
{
public long UserId { get; set; }
public User User { get; set; }
public long UserIAmFollowingId { get; set; }
public User UserIAmFollowing { get; set; }
}
这样,每个人都知道,当他们检查userfollowers
表时,userid
是跟踪的人的Id,而userfollowers
表则相反。如果我在系统中的Id是8,我可以这样查询我的追随者和我追随的人;
var myFollowers = _context.UserFollowers.Where(UserId = 8);
var peopleIFollow = _context.UserFollowing.Where(UserId = 8);