Discord.net |如何将属于数据库中人员的用户 ID 转换为可用于排行榜的用户名?



我正在为我的 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());

我希望看到的(如果这是数据库结构的来源,则从未看过 Discord)将是一个表格:

  • 行会
  • 经验
  • 用户

我希望dbContext.users有这样的东西:

UserId | UserName 

然后是一个公会表,如下所示:

GuildId | GuildName | UserId 

和体验,如下所示:

ExperienceId | UserId 

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

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

对我来说,这看起来像转换为 SQL 的 EF Core 查询:

select UserId from Guild

从这一点来看,我看到了一些潜在的问题:

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

更重要的是,您可以在 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 到 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();

请参阅代码中的注释:

//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,因为它是一种更有效的字符串构建方法。

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


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

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

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

相关内容

  • 没有找到相关文章

最新更新