I have the following method that I am trying to optimize. Currently, the method works great, however, it takes a little over 3 hours to complete. I feel like, using some nifty LINQ joins, it should be able to run in minutes. Here is the method:
public async Task UpdateEmailTable(IEnumerable<StudentEmail> 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++;
}
}
So this method is called with a list of student ids and emails. This list does not come from the database. This list comes from a web call and must be passed into the method. It then iterates through the list, one at a time. It takes the student's id and checks to see if it exists in the BarcDemoGraphicEmail table, there by setting the isIn flag.
If the student ID is NOT in the BarcDemoGraphicEmail table, it pulls the account information from another table called BarcAccount. It then inserts this student's email into the BarcDemoGraphicEmail using the information from the BarcAccount table and the email from the students current iteration.
If the student ID IS in the BarcDemoGraphicEmail table, it simply pulls that record and updates the UpdateDate field and the Email field from the current iteration.
As I said earlier, this method currently works fine, however it takes way too long. How can I optimize my code (or possibly optimize the database) so this executes faster?
This is a console .NET Core 3.1 C# application using Entity Framework Core 3.1. The database is a SQL Server database.
System.Data.SqlClientnamespace. You can handle your data as if it were in tables. But there is no C# code that will be faster than the DB itself. We had a 4+ hour process rewritten. As stored procedure it took about 12 seconds to complete. \$\endgroup\$StudentEmail,BarcDemoGraphicEmail,Barcaccount. Also, how many items willstudentscontain, typically? There seems to be much room for improvement but that's hard to tell now. \$\endgroup\$