【问题标题】:Discord.net | How can I turn the user ID's that belong to people in my database to usernames which I can use for my leaderboard?不和谐网 |如何将属于我数据库中人员的用户 ID 转换为可用于排行榜的用户名?
【发布时间】:2019-08-20 17:52:34
【问题描述】:

我正在为我的 Discord 机器人拥有的升级系统制作排行榜。该列表将列出拥有最多 XP 的人,并从最高到最低对他们进行排序。我已经实现了这个目标,但我只能在排行榜中他们的 XP 数量旁边显示用户 ID。如何将此用户 ID 转换为用户名?

foreach (ulong n in DbContext.Experiences.OrderByDescending(x => 
x.XP).Select(x => x.ID))
{
    Context.Guild.GetUser(n).ToString()
}

var leaderboard = string.Concat(DbContext.Experiences.OrderByDescending(x => 
x.XP).Select(x => $"Level {x.LevelNumber} with {x.XP} xp 
    {//username must be here}\n"));

await ReplyAsync(leaderboard.ToString());

【问题讨论】:

    标签: c# bots discord leaderboard discord.net


    【解决方案1】:

    假设您已经拥有所需的用户 ID

    Context.Guild.GetUser(THE_USER_ID_HERE).Username
    如果存在,则返回用户的用户名。

    如果您的排行榜是全局的(用户可能不在执行命令的服务器中)
    您可以改用client.GetUser(THE_USER_ID_HERE).Username,其中client 是您的机器人当前的套接字客户端。

    (或者,如果您希望显示与服务器绑定的用户名,也可以访问Nickname 属性)

    【讨论】:

    • 我以前试过这个,它适用于一个用户。但我希望它能够获取每个人的用户名,并且只有他们的 ID 作为参考。
    • @VACEfron 然后遍历他们的 ID 列表,然后使用指定的方法获取他们的用户名(将其传递到列表中以让您使用它做您想做的事情,或者将其添加到字符串构建器,如果您打算打印出所有用户名)。
    【解决方案2】:

    我希望看到的(如果这是数据库结构的来源,则永远不会查看 Discord)将是一个表:

    • 公会
    • 经验
    • 用户

    我希望 dbContext.Users 有类似的东西:

    UserId | UserName 
    

    然后是公会表,其中包含以下内容:

    GuildId | GuildName | UserId 
    

    和体验看起来像:

    ExperienceId | UserId 
    

    我会在这里继续做一些假设:

    Context.Guild.GetUser(n).ToString(); 
    

    在我看来,这就像一个转换为 SQL 的 EF Core 查询:

    select UserId from Guild
    

    据此,我发现了一些潜在问题:

    首先,Guild 方法只返回一个字符串或 long 很奇怪。如果这是您的实现,则返回一个对象。

    更重要的是,您可以在 1 个查询中执行此操作:

    在 Sql 中:

    Select g.GuildId, e.Experiece, u.UserId, u.UserName from Guild g
       left join Users u on g.UserId = u.UserId
       left join Experiences e on u.UserId = e.UserId
    where g.GuildId = @myGuildId
    order by e.Experience Desc
    

    这会给你返回如下行: 1 | 1500 | 10 |咬勺 1 | 1450 | 51 |丢失的肘部 1 | 1121 | 98 |地球天火 1 | 990 | 15 |金鹅

    我会做什么:创建一个视图类,并使用查询中的 AutoMapper 之类的东西映射它,或者在您具体化实例时映射它:

    创建一个类:

    public class LeaderView 
    {
        public string UserName {get; set;}
        public long UserId {get; set;}
        public long GuildId {get; set; }
        public int Experience { get; set; }
    }
    

    然后是 linq to Sql 查询,如:

    var leaders = from g in context.Guilds
    join u in context.Users on g.UserId = u.UserId
    join e in context.Experience on u.UserId  = e.UserId
    select new LeaderView
    {
        UserName = u.UserName,
        UserId = u.UserId,
        GuildId = g.UserId,
        Experience = e.Experience
    };  
    
    leaders = leaders.OrderByDescending(o => o.Experience);
    return leaders.ToList();
    

    【讨论】:

    • 如果我错了,请纠正我,但我认为您假设我将用户名存储在数据库中,而我没有。我已经知道如何获取每个人的用户 ID,但我希望将这些用户 ID 转换为用户名。但是,我可以选择列表中的第一个人并使用以下命令获取他的用户名:Context.Guild.GetUser(INSERT_ID) 但我希望为列表中的每个人都这样做,并在消息中使用结果。
    • 我是。上下文不是数据库上下文吗?我做了很多不熟悉不和谐的假设
    • 是的,DbContext 是一个数据库上下文。但是我没有将用户名存储在数据库中(否则会很简单哈哈)。
    【解决方案3】:

    查看代码中的 cmets:

    //What exactly is this for loop meant to do? 
    //You appear to be getting a user based on ID and doing nothing with that value.
    //This should be removed
    foreach (ulong n in DbContext.Experiences.OrderByDescending(x => 
    x.XP).Select(x => x.ID))
    {
       //While this is how to get a user by ID, you aren't actually doing anything with this once it's retrieved.
        Context.Guild.GetUser(n).ToString()
    }
    
    //You can simply fetch the username here, given that you have access to the ID
    var leaderboard = string.Concat(DbContext.Experiences.OrderByDescending(x => 
    x.XP).Select(x => $"Level {x.LevelNumber} with {x.XP} xp 
        {//username must be here}\n"));
    
    await ReplyAsync(leaderboard.ToString());
    

    您修改后的代码应如下所示:

    var leaderboard = string.Join("\n", DbContext.Experiences
                                                 .OrderByDescending(x => x.XP)
                                                 .Select(x => $"Level {x.LevelNumber} with {x.XP} xp {Context.Guild.GetUser(x.ID).ToString()}"));
    await ReplyAsync(leaderboard);
    

    注意:我已将 string.Concat 替换为 string.Join,因为它是一种更有效的字符串构建方法。

    【讨论】:

      猜你喜欢
      • 2019-08-06
      • 1970-01-01
      • 2021-05-22
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 2021-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多