c# - 带隧道到 MySQL 的 EF (C#) - 优化数据库调用

标签 c# mysql entity-framework

所以我有程序来处理 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 中有他们的玩家。如果这样的玩家不存在,则删除他的成就。

这一切都在做,所以我不会因为一次加载所有数据而使我的内存过载。

我知道问题在于在 foreach 步骤中检查数据库,但我无法弄清楚没有它该怎么做。我尝试的其他事情产生了错误,要么是因为 EF 无法将其转换为 SQL,要么是在尝试访问不存在的实体时抛出了异常。在 foreach 中执行此操作会导致整个程序出现瓶颈,这可能是因为对服务器执行 ping 操作。

我会更频繁地需要类似的东西,所以如果有人能帮助我制作它,我将非常感激,这样就不需要在“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 查询将比 Entity Framework 快一个数量级。

如果您想在应用程序中执行此操作,可以使用以下使用 LINQ to Entities 和 LINQ 扩展方法的代码。我假设您在 achievements 表中有一个 player_data 的外键,因此 Entity Framework 会为您的 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;
    }
}

关于c# - 带隧道到 MySQL 的 EF (C#) - 优化数据库调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31632901/

相关文章:

c# - 未记录的 Windows 内置 PDF 渲染器功能?

c# - 如何解析 HTML 节点的属性

c# - 如何在C#中设置ushort的最左和最右位

php - PDO 未输出正确的行数

entity-framework - Entity Framework 映射到查找表

c# - Xamarin.安卓。你调用的对象是空的。点击按钮

php - jquery从其他页面获取数据并输入表单字段

mysql - 先显示非空值的结果,然后显示空值的结果

c# - 在 Postgres SQL 连接失败时在本地保存数据的选项有哪些

entity-framework - 使用 Active Directory 集成身份验证的 Azure SQL 数据库连接无法打开