实体框架核心:流畅的api多对多

时间:2018-05-29 10:37:52

标签: c# asp.net asp.net-core entity-framework-core

如何对以下内容进行建模:用户拥有许多关注者并跟随许多用户。同一个用户有很多被阻止的用户(Twitter有点特色)。

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<User> Following { get; set; }
    public virtual ICollection<User> Followers { get; set; }
    public virtual ICollection<User> BlockedUsers { get; set; }
}

public class User
{
    public ApplicationUser User { get; set; }
    public string UserId { get; set; }
    public ApplicationUser Follower { get; set; }
    public string FollowerId { get; set; }
}

到目前为止我的实施:

public void Configure(EntityTypeBuilder<User> builder)
{
    builder.HasKey(k => new { k.UserId, k.FollowerId });

    builder.HasOne(l => l.User)
           .WithMany(a => a.Followers)
           .HasForeignKey(l => l.UserId);

    builder.HasOne(l => l.Follower)
           .WithMany(a => a.Following)
           .HasForeignKey(l => l.FollowerId);
}

如何实施阻止用户字段?

public virtual ICollection<User> BlockedUsers { get; set; }

1 个答案:

答案 0 :(得分:1)

正如在聊天中所讨论的,我很少相信EF的功能可用于多对多,无所谓的EF Core。这不是一个直接针对您的问题,而是解释了如果它是我的项目我将如何处理。

您已经拥有ApplicationUser,因此只有来自它们的表才能定义不同ApplicationUsers之间的关系。每个用户可以拥有多个内容:关注者,关注者和被阻止者。用户不能直接控制谁跟随他们,因此不需要自己的表。您可以通过查看关注者表来确定谁跟随用户。

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<UserFollow> Following { get; set; }
    public virtual ICollection<UserFollow> Followers { get; set; }
    public virtual ICollection<UserBlock> BlockedUsers { get; set; }
}

public class UserFollow
{
    public int Id { get; set; }

    [ForeignKey(nameof(SourceUserId))]
    public ApplicationUser SourceUser { get; set; }
    public string SourceUserId { get; set; }

    [ForeignKey(nameof(FollowedUserId))]
    public ApplicationUser FollowedUser { get; set; }
    public string FollowedUserId { get; set; }
}

public class UserBlock
{
    public int Id { get; set; }

    [ForeignKey(nameof(SourceUserId))]
    public ApplicationUser SourceUser { get; set; }
    public string SourceUserId { get; set; }

    [ForeignKey(nameof(BlockedUserId))]
    public ApplicationUser BlockedUser { get; set; }
    public string BlockedUserId { get; set; }
}

您的配置不会发生太大变化(请考虑此伪装,未经测试):

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    moderlBuilder.Entity<UserFollow>()
           .HasOne(l => l.SourceUser)
           .WithMany(a => a.Following)
           .HasForeignKey(l => l.SourceUserId);

    moderlBuilder.Entity<UserFollow>()
           .HasOne(l => l.FollowedUser)
           .WithMany(a => a.Followers)
           .HasForeignKey(l => l.FollowedUserId);

    moderlBuilder.Entity<UserBlock>()
           .HasOne(l => l.SourceUser)
           .WithMany(a => a.BlockedUsers)
           .HasForeignKey(l => l.SourceUserId);
}

(注意我总是在一个简单的密钥(Id上只是为了便于查询),但您可以根据需要将其更改为复合密钥。

相关问题