我有以下方法,我正在尝试优化。目前,该方法工作很好,然而,它需要3个多小时才能完成。我觉得,使用一些巧妙的LINQ连接,它应该能够在几分钟内运行。以下是一种方法:
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 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 表中。
BarcDemoGraphicEmail
isIn
如果学生ID不在 BarcDemoGraphicEmail 表中,它将从另一个名为 BarcAccount 的表中提取帐户信息。然后,它使用来自 BarcDemoGraphicEmail 表的信息和来自 students 当前迭代的电子邮件将学生的电子邮件插入到 D7 中。
BarcAccount
students
D7
如果学生ID位于 BarcDemoGraphicEmail 表中,它只需提取该记录并从当前迭代中更新 UpdateDate 字段和 Email 字段。
UpdateDate
Email
正如我前面说过的,这个方法目前运行良好,但是它花费的时间太长了。我如何优化我的代码(或者可能优化数据库),使其执行得更快?
这是一个使用EntityFrameworkCore3.1的控制台.NET Core3.1 C#应用程序。数据库是Server数据库。
发布于 2020-12-15 08:30:56
一些简短的评论:
DemoGraphic
Barcaccount
Sridentifier
Updatedate
Aridentifier
ar
sr
UpdateEmailTable(IEnumerable students)
var studentEmails = students.ToList();
List studentEmails
ICollection studentEmails
Console.WriteLine
您说这需要三个小时,这表明要么是大量的数据,要么是特别慢的代码(或者您的表没有正确地编入索引?)也许使用SqlBulkInsert的实现逻辑可以解决性能问题。也许将传入的数据存储在一个表中,然后应用一两个SQL查询来更新BarcDemoGraphicEmail中的数据。
发布于 2020-12-15 04:25:37
您可以在相同的循环迭代中查询同一 BarcDemoGraphicEmail 表两次。
您可以如下所示改进查询
var rec = await _context.BarcDemoGraphicEmail .FirstOrDefaultAsync(z => z.Sridentifier == student.StudentId); if (rec == null) var ar = ...