Discord.net |如何将属于我数据库中人员的用户 ID 转换为可用于排行榜的用户名?
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?
我正在为我的 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());
假设您已经拥有所需的用户 ID
Context.Guild.GetUser(THE_USER_ID_HERE).Username
此 return 用户的用户名(如果存在)。
如果您的排行榜是全局的(用户可能不在执行命令的服务器中)
,您可以使用 client.GetUser(THE_USER_ID_HERE).Username
,其中 client
是您的bot 的当前套接字客户端。
(或者,如果您希望显示绑定到服务器的用户名,则访问 Nickname
属性)
我希望看到的(如果数据库结构来自 Discord,则从不查看)将是 table for:
- 公会
- 经验
- 用户
我希望 dbContext.Users 有这样的东西:
UserId | UserName
然后是公会 table 有这样的东西:
GuildId | GuildName | UserId
和体验看起来像:
ExperienceId | UserId
这里我继续做一些假设:
Context.Guild.GetUser(n).ToString();
这对我来说看起来像是转换为 SQL:
的 EF Core 查询
select UserId from Guild
据此,我发现了一些潜在问题:
首先,Guild 方法只返回一个字符串或长整数很奇怪。 Return一个对象,如果这是你的实现。
更重要的是,您可以在 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 |金鹅
我会做什么:创建一个视图 class,然后使用查询中的 AutoMapper 之类的东西映射它,或者在具体化实例时映射它:
制作class:
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();
查看代码中的注释:
//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
,因为它是一种更高效的字符串构建方法。
我正在为我的 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());
假设您已经拥有所需的用户 ID
Context.Guild.GetUser(THE_USER_ID_HERE).Username
此 return 用户的用户名(如果存在)。
如果您的排行榜是全局的(用户可能不在执行命令的服务器中)
,您可以使用 client.GetUser(THE_USER_ID_HERE).Username
,其中 client
是您的bot 的当前套接字客户端。
(或者,如果您希望显示绑定到服务器的用户名,则访问 Nickname
属性)
我希望看到的(如果数据库结构来自 Discord,则从不查看)将是 table for:
- 公会
- 经验
- 用户
我希望 dbContext.Users 有这样的东西:
UserId | UserName
然后是公会 table 有这样的东西:
GuildId | GuildName | UserId
和体验看起来像:
ExperienceId | UserId
这里我继续做一些假设:
Context.Guild.GetUser(n).ToString();
这对我来说看起来像是转换为 SQL:
的 EF Core 查询select UserId from Guild
据此,我发现了一些潜在问题:
首先,Guild 方法只返回一个字符串或长整数很奇怪。 Return一个对象,如果这是你的实现。
更重要的是,您可以在 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 |金鹅
我会做什么:创建一个视图 class,然后使用查询中的 AutoMapper 之类的东西映射它,或者在具体化实例时映射它:
制作class:
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();
查看代码中的注释:
//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
,因为它是一种更高效的字符串构建方法。