首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用LINQ优化数据库访问

使用LINQ优化数据库访问
EN

Code Review用户
提问于 2020-12-14 15:49:11
回答 2查看 132关注 0票数 1

我有以下方法,我正在尝试优化。目前,该方法工作很好,然而,它需要3个多小时才能完成。我觉得,使用一些巧妙的LINQ连接,它应该能够在几分钟内运行。以下是一种方法:

代码语言:javascript
运行
复制
    public async Task UpdateEmailTable(IEnumerable students)
    {
        Console.WriteLine("Updating Email table");
        var studentEmails = students.ToList();
        int totalStudents = studentEmails.Count;
        int currentCount = 0;
        float lastPercentage = -1;

        foreach (var student in studentEmails)
        {
            var isIn = await _context.BarcDemoGraphicEmail.AnyAsync(z => z.Sridentifier == student.StudentId);

            if (!isIn)
            {
                var ar = await _context.Barcaccount.FirstOrDefaultAsync(z => z.SrIdentifier == student.StudentId);

                await _context.BarcDemoGraphicEmail.AddAsync(new BarcDemoGraphicEmail
                {
                    Sridentifier = student.StudentId,
                    Email = student.EmailAddress,
                    Updatedate = DateTime.Now,
                    Aridentifier = ar == null ? "" : ar.ArIdentifier
                });
            }
            else
            {
                var rec = await _context.BarcDemoGraphicEmail.Where(z => z.Sridentifier == student.StudentId)
                    .FirstAsync();
                rec.Email = student.EmailAddress;
                rec.Updatedate = DateTime.Now;
            }

            await _context.SaveChangesAsync();

            int percentage = (int)Math.Round((float)currentCount / totalStudents * 100);
            if (lastPercentage != percentage) Console.Write("\r" + percentage + "%");
            lastPercentage = percentage;
            currentCount++;
        }
    }

因此,这个方法是通过学生ids和电子邮件列表调用的。此列表不来自数据库。此列表来自web调用,必须传递到方法中。然后,它遍历列表,一次一个。它接受学生的id,并通过设置BarcDemoGraphicEmail标志来检查它是否存在于isIn表中。

如果学生ID不在BarcDemoGraphicEmail表中,它将从另一个名为BarcAccount的表中提取帐户信息。然后,它使用来自BarcDemoGraphicEmail表的信息和来自students当前迭代的电子邮件将学生的电子邮件插入到D7中。

如果学生ID位于BarcDemoGraphicEmail表中,它只需提取该记录并从当前迭代中更新UpdateDate字段和Email字段。

正如我前面说过的,这个方法目前运行良好,但是它花费的时间太长了。我如何优化我的代码(或者可能优化数据库),使其执行得更快?

这是一个使用EntityFrameworkCore3.1的控制台.NET Core3.1 C#应用程序。数据库是Server数据库。

EN

回答 2

Code Review用户

发布于 2020-12-15 08:30:56

一些简短的评论:

  • DemoGraphic不是一个复合词,所以中间不应该有大写字母。然而,Barcaccount是如此,它应该被称为BarcAccountSridentifierUpdatedateAridentifier也一样。
  • 使用有意义的变量名。我不知道ar是什么,或者sr
  • UpdateEmailTable(IEnumerable students)var studentEmails = students.ToList();使用正确命名和类型的参数。您的方法需要一个List studentEmails (或者ICollection studentEmails),这样编写它,并使调用代码传递正确的参数。
  • 这种方法充满了Console.WriteLine。这意味着它混合了业务逻辑和UI。馊主意。至少将其更改为使用日志系统,然后将其配置为将其输出到命令行。

您说这需要三个小时,这表明要么是大量的数据,要么是特别慢的代码(或者您的表没有正确地编入索引?)也许使用SqlBulkInsert的实现逻辑可以解决性能问题。也许将传入的数据存储在一个表中,然后应用一两个SQL查询来更新BarcDemoGraphicEmail中的数据。

票数 2
EN

Code Review用户

发布于 2020-12-15 04:25:37

您可以在相同的循环迭代中查询同一BarcDemoGraphicEmail表两次。

您可以如下所示改进查询

代码语言:javascript
运行
复制
var rec = await _context.BarcDemoGraphicEmail
    .FirstOrDefaultAsync(z => z.Sridentifier == student.StudentId);

if (rec == null)
{
    var ar = ...
    ...
}
else
{
    rec.Email = student.EmailAddress;
    rec.Updatedate = DateTime.Now;
}

此外,还应该将.ConfigureAwait(false)添加到所有异步方法中。

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/253464

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档