EF (c#)与隧道到MySQL -优化数据库调用
本文关键字:MySQL 优化 数据库 调用 隧道 EF | 更新日期: 2023-09-27 18:04:45
所以我有程序来处理MySQL数据库中的一些工作。我用putty通过SSH隧道连接(是的,我知道在服务器上启动程序会更好,但我没有选择在这里)。
我的程序速度有些问题。我通过添加"。include (table_name)"解决了一个问题,但我想不出在这里做的方法。
因此,该方法的目的是清理数据库中不需要的、损坏的记录。简化后的代码如下所示:
using (var dbContext = new MyDatabase_dataEntities())
{
List<achievements> achiList = new List<achievements>();
var achievementsQuery = from data in dbContext.achievements
orderby data.playerID
select data;
achiList = achievementsQuery.Skip(counter * 5000).Take(5000).ToList();
foreach (achievements record in achiList)
{
var playerExists = from data in dbContext.players_data
where data.playerID == record.playerID
select data;
if(!playerExists.Any())
{
dbContext.achievements.Remove(record);
}
}
dbContext.SaveChanges();
counter++;
}
所以这是这样构建的,因为我想加载成就表,然后检查成就是否有他们的球员在player_data。如果这样的玩家不存在,删除他的成就。
这都是在做的,所以我不会因为一次加载所有的数据而使内存过载。
我知道问题是在每一步检查数据库,但我不知道如何做到这一点,没有它。我尝试的其他事情会产生错误,因为EF无法将其转换为SQL,或者在试图访问不存在的实体时抛出异常。
我将需要类似的事情更经常,所以我会非常感激,如果有人能帮助我使它,所以没有必要调用数据库在"foreach"。我知道我可以尝试加载整个players_data表,然后检查Any(),但有些表我需要它太大了。
哦,关闭跟踪更改在这一点上没有帮助,因为它不是减慢程序的原因。
我将感激任何帮助,提前感谢!
编辑:嗯,有没有一种方法来获得成就,没有player_data对应他们通过一个查询使用关联?比如在成就查询中添加如下内容:
where !data.player_data.Exists()
Intellisense告诉我,此时没有类似Exists或Any的东西可以使用。有类似的技巧吗?它肯定会处理我的速度问题,因为在foreach中不需要数据库调用。
如果你想删除没有相应用户记录的成就,那么你可以使用下面的SQL查询:
DELETE a
FROM `achievements` a
LEFT JOIN `user` AS u
ON u.`playerID` = a.`playerID`
WHERE u.`playerID` IS NULL;
SQL查询将比实体框架快一个数量级。
如果你想在应用程序中做到这一点,你可以使用下面的代码,使用LINQ到实体和LINQ扩展方法。我假设您在achievements
表中有player_data
的外键,因此实体框架为您的achievements
实体生成player_data
惰性属性:
using (var dbContext = new MyDatabase_dataEntities())
{
var proceed = true;
while (proceed)
{
// Get net 1000 entities to delete
var entitiesToDelete = dbContext.achievements
.Where(x => x.players_data == null)
.Take(1000)
.ToList();
dbContext.achievements.RemoveRange(entitiesToDelete);
dbContext.SaveChanges();
// Proceed if deleted entities during this iteration
proceed = entitiesToDelete.Count() > 0;
}
}
如果您喜欢使用LINQ查询语法而不是扩展方法,那么您的代码将看起来像:
using (var dbContext = new MyDatabase_dataEntities())
{
var proceed = true;
while (proceed)
{
// Get net 1000 entities to delete
var query = from achievement in dbContext.achievements
where achievement.players_data == null
select achievement;
var entitiesToDelete = query.ToList();
dbContext.achievements.RemoveRange(entitiesToDelete);
dbContext.SaveChanges();
// Proceed if deleted entities during this iteration
proceed = entitiesToDelete.Count() > 0;
}
}