0

I am using async programming in my c# and I am trying to update data into the db on checking if the records exist else add new record

var existingStudent = await CheckIfStudentExists(student); // check if the Student with the StudentCode is already exist

if (existingStudent is null)
{
    await _context.Students.AddAsync(student);
    await SaveChanges();
}
else
{
    student.StudentId = existingStudent.StudentId;
    _context.Students.Update(student);
    await SaveChanges();
}

Since here I am uploading bulk files (say around 7000) in one shot. It happens that the same StudentCode with 2 different files can comeup. Many times I have observed that ADD part of the code is executed without checking if the student exists.

What is the change I need to do so that If-Else condition is not executed till the CheckIfStudentExists is executed.

1
  • 1
    if (existingStudent == null) ? Commented Dec 16, 2020 at 10:06

2 Answers 2

1

Well, this code is vulnerable to race condition. Nothing stops two threads checking that student does not exists and enter block of a code where you insert student. This leads to the same student inserted twice.

What you can do is to use some synchronization technique, like locks or semaphore. I will present you the simpliest lock, but it is up to you to choose for yourself how you want synchronize threads.

// somewhere in a class define
private readonly object syncObject = new object();

// and use it in the method
lock(syncObject)
{
    var existingStudent = await CheckIfStudentExists(student); // check if the Student with the StudentCode is already exist

    if (existingStudent is null)
    {
        await _context.Students.AddAsync(student);
        await SaveChanges();
    }
    else
    {
        student.StudentId = existingStudent.StudentId;
        _context.Students.Update(student);
        await SaveChanges();
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Is there any better way ? not sure I will be allowed to use Lock in this case , as it is costly .
@amitagarwal Well, there are plenty of synchronization tools. Semaphore, SemaphoreSlim, Monitor to name a few.
I checked using lock . And lock do not support await.
@amitagarwal check out the SemaphoreSlim.WaitAsync method. It is used by opening a try/finally block immediately after the await WaitAsync, and calling Release inside the finally. The protected region is inside the try.
0
if (existingStudent == null)
{
    await _context.Students.AddAsync(student);
    await SaveChanges();
}
else
{
    student.StudentId = existingStudent.StudentId;
    _context.Students.Update(student);
    await SaveChanges();
}

3 Comments

existingStudent is null and existingStudent == null both does the same thing ?
they are different look at link
While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply. From Review

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.