Entity Framework Core Fluent API:如何实现用户关注与拉黑功能?
实现拉黑功能的完整方案
首先得说,你现在的User类命名有点坑——它其实是处理关注关系的中间表,但名字和ApplicationUser太像了,很容易搞混。先把这个重构清楚,再搞拉黑功能会顺畅很多。
第一步:重构关注关系的实体
把原来的User类改名为UserFollow,明确它是关注关系的中间表:
public class UserFollow { // 被关注者的ID public string UserId { get; set; } public ApplicationUser User { get; set; } // 发起关注者的ID public string FollowerId { get; set; } public ApplicationUser Follower { get; set; } }
然后同步修改ApplicationUser里的关注相关属性:
public class ApplicationUser : IdentityUser { // 我关注的人(通过UserFollow的Follower关联) public virtual ICollection<UserFollow> Following { get; set; } = new List<UserFollow>(); // 关注我的人(通过UserFollow的User关联) public virtual ICollection<UserFollow> Followers { get; set; } = new List<UserFollow>(); // 我们要实现的拉黑集合,先改成对应中间表的类型 public virtual ICollection<UserBlock> BlockedUsers { get; set; } = new List<UserBlock>(); }
第二步:创建拉黑关系的中间实体
拉黑是单向关系(我拉黑你,你不需要知道/记录),所以单独建一个UserBlock实体来存储拉黑记录,还能方便后续扩展(比如加拉黑时间、拉黑原因等):
public class UserBlock { // 拉黑者的ID public string BlockerId { get; set; } public ApplicationUser Blocker { get; set; } // 被拉黑者的ID public string BlockedUserId { get; set; } public ApplicationUser BlockedUser { get; set; } }
第三步:配置拉黑关系的EF Core映射
在DbContext的OnModelCreating里添加UserBlock的配置:
public void Configure(EntityTypeBuilder<UserBlock> builder) { // 复合主键:确保同一个用户不能重复拉黑同一个人 builder.HasKey(k => new { k.BlockerId, k.BlockedUserId }); // 配置拉黑者的关联:一个用户可以拉黑多个人,对应ApplicationUser的BlockedUsers集合 builder.HasOne(b => b.Blocker) .WithMany(u => u.BlockedUsers) .HasForeignKey(b => b.BlockerId) .OnDelete(DeleteBehavior.Cascade); // 如果拉黑者账号被删除,同步删除拉黑记录 // 配置被拉黑者的关联:一个用户可以被多个人拉黑 // 如果不需要在ApplicationUser里加"被谁拉黑"的反向集合,这里用.WithMany()就行 builder.HasOne(b => b.BlockedUser) .WithMany() .HasForeignKey(b => b.BlockedUserId) .OnDelete(DeleteBehavior.Restrict); // 避免删除被拉黑用户时,连带删除其他用户的拉黑记录 }
可选:添加"被谁拉黑"的反向导航
如果你需要查询某个用户被哪些人拉黑了,可以在ApplicationUser里加一个反向集合:
public virtual ICollection<UserBlock> BlockedBy { get; set; } = new List<UserBlock>();
然后修改UserBlock的配置:
builder.HasOne(b => b.BlockedUser) .WithMany(u => u.BlockedBy) .HasForeignKey(b => b.BlockedUserId) .OnDelete(DeleteBehavior.Restrict);
为什么不用直接的ICollection<ApplicationUser>?
EF Core 5+支持无中间实体的多对多,但拉黑这种单向关系用中间实体更灵活——不仅能清晰区分"拉黑者"和"被拉黑者",还能随时扩展字段(比如拉黑时间),后期维护成本更低。
内容的提问来源于stack exchange,提问作者FrankDupree
相关产品推荐
相关产品推荐

