sql—存储用户的上/下投票帖子

nkhmeac6  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(435)

我有下面的模式,其中一个appuser可以有许多userpost(用户自己的post),也可以向上/向下投票其他用户的post。

public class AppUser {
    public string Id {get;set;}
    public ICollection<Post> UserPosts {get; set;}

    public ICollection<Post> UpvotedPosts {get;set;}
    public ICollection<Post> DownvotedPosts {get;set;}
}

public class Post {
    public string Id {get;set;}
    public string Content {get;set;}

    public string AppUserId {get;set;}
    public AppUser AppUser {get;set;}
}

我正在试图找出上/下投票的帖子和appuser之间的关系。我认为应该是1对多(一个应用程序用户可以有很多向上/向下投票的帖子-每个帖子只能有一个应用程序用户)。
但是按照这种思路,它会引起与userposts的冲突——因为我还定义了一个appuser可以有很多post,而一个post只能有一个user。
推荐的方法是什么?

yshpjwxd

yshpjwxd1#

你想要的是一种多对多的关系 AppUser 以及 Post . 您可以引入一个名为 Vote 代表多对多关系。
以下完全工作的控制台示例演示了此方法:

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace IssueConsoleTemplate
{
    public class AppUser
    {
        public string Id { get; set; }
        public ICollection<Post> UserPosts { get; set; }
        public ICollection<Vote> UserVotes { get; set; }
    }

    public class Post
    {
        public string Id { get; set; }
        public string Content { get; set; }
        public string AppUserId { get; set; }

        public AppUser AppUser { get; set; }
        public ICollection<Vote> UserVotes { get; set; }
    }

    // Implements a many-to-many relationship between
    // AppUser and Post.
    public class Vote
    {
        public string AppUserId { get; set; }
        public string PostId { get; set; }
        public int Value { get; set; }

        public AppUser AppUser { get; set; }
        public Post Post { get; set; }
    }

    public class Context : DbContext
    {
        public DbSet<AppUser> AppUsers { get; set; }
        public DbSet<Post> Posts { get; set; }
        public DbSet<Vote> Votes { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseSqlServer(@"Data Source=.\MSSQL14;Integrated Security=SSPI;Initial Catalog=So63012999")
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<AppUser>(
                entity =>
                {
                    entity.HasData(
                        new AppUser {Id = "John"},
                        new AppUser {Id = "Sam"},
                        new AppUser {Id = "Steve"});
                });

            modelBuilder.Entity<Post>(
                entity =>
                {
                    entity.HasData(
                        new Post
                        {
                            Id = "John-01",
                            AppUserId = "John",
                            Content = "My first post!"
                        },
                        new Post
                        {
                            Id = "Sam-01",
                            AppUserId = "Sam",
                            Content = "What?"
                        },
                        new Post
                        {
                            Id = "Sam-02",
                            AppUserId = "Sam",
                            Content = "Where?"
                        },
                        new Post
                        {
                            Id = "Sam-03",
                            AppUserId = "Sam",
                            Content = "Who?"
                        },
                        new Post
                        {
                            Id = "Steve-01",
                            AppUserId = "Steve",
                            Content = "Are we there yet?"
                        });
                });

            modelBuilder.Entity<Vote>(
                entity =>
                {
                    entity.HasKey(e => new {e.AppUserId, e.PostId});

                    entity.HasOne(e => e.AppUser)
                        .WithMany(e => e.UserVotes)
                        .HasForeignKey(e => e.AppUserId);

                    entity.HasOne(e => e.Post)
                        .WithMany(e => e.UserVotes)
                        .HasForeignKey(e => e.PostId);

                    entity.HasData(
                        new Vote { AppUserId = "John", PostId = "Sam-01", Value = 1},
                        new Vote { AppUserId = "John", PostId = "Sam-02", Value = 1},
                        new Vote { AppUserId = "John", PostId = "Sam-03", Value = -1},
                        new Vote { AppUserId = "Steve", PostId = "Sam-03", Value = -1});
                });
        }
    }

    internal static class Program
    {
        private static void Main()
        {
            using var context = new Context();

            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();

            var users = context.AppUsers
                .OrderBy(u => u.Id)
                .ToList();

            var postsWithVotes = context.Votes
                .Include(v => v.Post)
                .ToList();

            var postsWithNegativeVotes = context.Votes
                .Include(v => v.Post)
                .Where(v => v.Value < 0)
                .Select(v => v.Post)
                .Distinct()
                .ToList();

            Debug.Assert(users.Count == 3);
            Debug.Assert(postsWithVotes.Count == 4);
            Debug.Assert(postsWithNegativeVotes.Count == 1);
        }
    }
}

查看ef核心文档,了解更多关于多对多关系(或wikipedia)的信息。
在实际应用程序中,您可能还需要将密钥的类型从 stringint , long 或者 Guid .

相关问题