提问者:小点点

如何在EF Core5中映射Twitter follower/follower类型关系


如何使用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表,而不需要查看用户的导航属性。


共1个答案

匿名用户

试着像这样配置它。

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);