所以我有程序来处理MySQL数据库中的某些工作。我通过SSH隧道连接与putty连接(是的,我知道在服务器上启动程序会好得多,但我在这里没有选择)。
程序速度有问题。我通过添加“.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中有他们的玩家。如果此类播放器不存在,请删除其成就。
这一切都在做,所以我不会通过一次加载所有数据来重载我的内存。
我知道问题在于在foreach步骤中检入数据库,但如果没有它,我无法弄清楚如何做到这一点。我试过的其他事情也会产生错误,因为EF无法将其转换为SQL,或者在尝试访问不存在的实体时抛出了异常。在foreach瓶颈做整个程序可能是因为ping到服务器。
我会更频繁地需要类似的东西,所以如果有人能帮助我做到这一点我真的很感激,所以不需要在“foreach”中调用数据库。我知道我可以尝试加载整个players_data表然后检查Any(),但是我需要它的一些表太大了。
哦,关闭跟踪更改在这一点上没有帮助,因为它不会减慢程序的速度。
我会感激任何帮助,提前谢谢!
编辑:嗯,有没有办法通过使用关联的一个查询获得没有与其对应的player_data的成就?就像添加成就查询一样:where !data.player_data.Exists()
Intellisense告诉我,此时没有像Exists或Any这样的东西。有没有类似的伎俩?它肯定会处理我在速度上遇到的问题,因为不需要在foreach中调用数据库。
答案 0 :(得分:1)
如果您要删除没有相应用户记录的成就,那么您可以在下面使用SQL查询:
DELETE a
FROM `achievements` a
LEFT JOIN `user` AS u
ON u.`playerID` = a.`playerID`
WHERE u.`playerID` IS NULL;
SQL查询将比实体框架快一个数量级。
如果要在应用程序中执行此操作,可以使用以下使用LINQ to Entities和LINQ扩展方法的代码。我假设您在player_data
表中有achievements
的外键,因此Entity Framework为您的player_data
实体生成achievements
懒惰属性:
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;
}
}