Converted many raw sql queries to their linq2db equivalents

This commit is contained in:
Kwoth
2022-03-20 19:31:04 +01:00
parent fd032d3e91
commit 86e728b753
6 changed files with 36 additions and 97 deletions

View File

@@ -84,77 +84,6 @@ public static class DiscordUserExtensions
item.CurrencyAmount = 0; item.CurrencyAmount = 0;
} }
public static bool TryUpdateCurrencyState(
this NadekoContext ctx,
ulong userId,
string name,
string discrim,
string avatarId,
long amount,
bool allowNegative = false)
{
if (amount == 0)
return true;
// if remove - try to remove if he has more or equal than the amount
// and return number of rows > 0 (was there a change)
if (amount < 0 && !allowNegative)
{
var rows = ctx.Database.ExecuteSqlInterpolated($@"
UPDATE DiscordUser
SET CurrencyAmount=CurrencyAmount+{amount}
WHERE UserId={userId} AND CurrencyAmount>={-amount};");
return rows > 0;
}
// if remove and negative is allowed, just remove without any condition
if (amount < 0 && allowNegative)
{
var rows = ctx.Database.ExecuteSqlInterpolated($@"
UPDATE DiscordUser
SET CurrencyAmount=CurrencyAmount+{amount}
WHERE UserId={userId};");
return rows > 0;
}
// if add - create a new user with default values if it doesn't exist
// if it exists, sum current amount with the new one, if it doesn't
// he just has the new amount
var updatedUserData = !string.IsNullOrWhiteSpace(name);
name ??= "Unknown";
discrim ??= "????";
avatarId ??= "";
// just update the amount, there is no new user data
if (!updatedUserData)
{
ctx.Database.ExecuteSqlInterpolated($@"
UPDATE OR IGNORE DiscordUser
SET CurrencyAmount=CurrencyAmount+{amount}
WHERE UserId={userId};
INSERT OR IGNORE INTO DiscordUser (UserId, Username, Discriminator, AvatarId, CurrencyAmount, TotalXp)
VALUES ({userId}, {name}, {discrim}, {avatarId}, {amount}, 0);
");
}
else
{
ctx.Database.ExecuteSqlInterpolated($@"
UPDATE OR IGNORE DiscordUser
SET CurrencyAmount=CurrencyAmount+{amount},
Username={name},
Discriminator={discrim},
AvatarId={avatarId}
WHERE UserId={userId};
INSERT OR IGNORE INTO DiscordUser (UserId, Username, Discriminator, AvatarId, CurrencyAmount, TotalXp)
VALUES ({userId}, {name}, {discrim}, {avatarId}, {amount}, 0);
");
}
return true;
}
public static decimal GetTotalCurrency(this DbSet<DiscordUser> users) public static decimal GetTotalCurrency(this DbSet<DiscordUser> users)
=> users.Sum((Func<DiscordUser, decimal>)(x => x.CurrencyAmount)); => users.Sum((Func<DiscordUser, decimal>)(x => x.CurrencyAmount));

View File

@@ -1,4 +1,6 @@
#nullable disable #nullable disable
using LinqToDB;
using LinqToDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NadekoBot.Db.Models; using NadekoBot.Db.Models;
using NadekoBot.Services.Database; using NadekoBot.Services.Database;
@@ -75,11 +77,22 @@ public static class WaifuExtensions
.Select(x => x.Waifu.UserId) .Select(x => x.Waifu.UserId)
.FirstOrDefault(); .FirstOrDefault();
public static WaifuInfoStats GetWaifuInfo(this NadekoContext ctx, ulong userId) public static async Task<WaifuInfoStats> GetWaifuInfoAsync(this NadekoContext ctx, ulong userId)
{ {
ctx.Database.ExecuteSqlInterpolated($@" await ctx.WaifuInfo
INSERT OR IGNORE INTO WaifuInfo (AffinityId, ClaimerId, Price, WaifuId) .ToLinqToDBTable()
VALUES ({null}, {null}, {1}, (SELECT Id FROM DiscordUser WHERE UserId={userId}));"); .InsertOrUpdateAsync(() => new()
{
AffinityId = null,
ClaimerId = null,
Price = 1,
WaifuId = ctx.DiscordUser.Where(x => x.UserId == userId).Select(x => x.Id).First()
},
_ => new(),
() => new()
{
WaifuId = ctx.DiscordUser.Where(x => x.UserId == userId).Select(x => x.Id).First()
});
var toReturn = ctx.WaifuInfo.AsQueryable() var toReturn = ctx.WaifuInfo.AsQueryable()
.Where(w => w.WaifuId .Where(w => w.WaifuId

View File

@@ -102,17 +102,16 @@ public class GamblingService : INService, IReadyExecutor
if (maxDecay == 0) if (maxDecay == 0)
maxDecay = int.MaxValue; maxDecay = int.MaxValue;
await uow.Database.ExecuteSqlInterpolatedAsync($@" var decay = (double)config.Decay.Percent;
UPDATE DiscordUser await uow.DiscordUser
SET CurrencyAmount= .Where(x => x.CurrencyAmount > config.Decay.MinThreshold && x.UserId != _client.CurrentUser.Id)
CASE WHEN .UpdateAsync(old => new()
{maxDecay} > ROUND(CurrencyAmount * {config.Decay.Percent} - 0.5) {
THEN CurrencyAmount =
CurrencyAmount - ROUND(CurrencyAmount * {config.Decay.Percent} - 0.5) maxDecay > Sql.Round((old.CurrencyAmount * decay) - 0.5)
ELSE ? (long)(old.CurrencyAmount - Sql.Round((old.CurrencyAmount * decay) - 0.5))
CurrencyAmount - {maxDecay} : old.CurrencyAmount - maxDecay
END });
WHERE CurrencyAmount > {config.Decay.MinThreshold} AND UserId!={_client.CurrentUser.Id};");
_cache.SetLastCurrencyDecay(); _cache.SetLastCurrencyDecay();
await uow.SaveChangesAsync(); await uow.SaveChangesAsync();

View File

@@ -236,9 +236,9 @@ public partial class Gambling
public partial Task WaifuInfo(ulong targetId) public partial Task WaifuInfo(ulong targetId)
=> InternalWaifuInfo(targetId); => InternalWaifuInfo(targetId);
private Task InternalWaifuInfo(ulong targetId, string name = null) private async Task InternalWaifuInfo(ulong targetId, string name = null)
{ {
var wi = _service.GetFullWaifuInfoAsync(targetId); var wi = await _service.GetFullWaifuInfoAsync(targetId);
var affInfo = _service.GetAffinityTitle(wi.AffinityCount); var affInfo = _service.GetAffinityTitle(wi.AffinityCount);
var waifuItems = _service.GetWaifuItems().ToDictionary(x => x.ItemEmoji, x => x); var waifuItems = _service.GetWaifuItems().ToDictionary(x => x.ItemEmoji, x => x);
@@ -280,7 +280,7 @@ public partial class Gambling
true) true)
.AddField(GetText(strs.gifts), itemsStr, true); .AddField(GetText(strs.gifts), itemsStr, true);
return ctx.Channel.EmbedAsync(embed); await ctx.Channel.EmbedAsync(embed);
} }
[Cmd] [Cmd]

View File

@@ -385,10 +385,10 @@ public class WaifuService : INService, IReadyExecutor
return true; return true;
} }
public WaifuInfoStats GetFullWaifuInfoAsync(ulong targetId) public async Task<WaifuInfoStats> GetFullWaifuInfoAsync(ulong targetId)
{ {
using var uow = _db.GetDbContext(); await using var uow = _db.GetDbContext();
var wi = uow.GetWaifuInfo(targetId); var wi = await uow.GetWaifuInfoAsync(targetId);
if (wi is null) if (wi is null)
{ {
wi = new() wi = new()
@@ -409,12 +409,12 @@ public class WaifuService : INService, IReadyExecutor
return wi; return wi;
} }
public WaifuInfoStats GetFullWaifuInfoAsync(IGuildUser target) public async Task<WaifuInfoStats> GetFullWaifuInfoAsync(IGuildUser target)
{ {
using var uow = _db.GetDbContext(); await using var uow = _db.GetDbContext();
_ = uow.GetOrCreateUser(target); _ = uow.GetOrCreateUser(target);
return GetFullWaifuInfoAsync(target.Id); return await GetFullWaifuInfoAsync(target.Id);
} }
public string GetClaimTitle(int count) public string GetClaimTitle(int count)

View File

@@ -78,8 +78,6 @@ public class RemindService : INService
.ToLinqToDBTable() .ToLinqToDBTable()
.Where(x => x.ServerId / 4194304 % (ulong)_creds.TotalShards == (ulong)_client.ShardId .Where(x => x.ServerId / 4194304 % (ulong)_creds.TotalShards == (ulong)_client.ShardId
&& x.When < now) && x.When < now)
// .FromSqlInterpolated(
// $"select * from reminders where ((serverid >> 22) % {_creds.TotalShards}) == {_client.ShardId} and \"when\" < {now};")
.ToListAsyncLinqToDB(); .ToListAsyncLinqToDB();
} }