Vitor Durante
Vitor Durante

Reputation: 1073

How to deal with concurrency on EF Core

I have a method that searches for an entity on database and attempts to create it if it doesn't exist. As an example:

public async Country FindOrCreate(string name)
{
    var country = _context.Countries.FirstOrDefault(p => p.Name == name);

    if (country != null)
        return country;

    country = new Country
    {
        Name = name
    };

    _context.Countries.Add(country);
    _context.SaveChanges();

    return country;
}

The problem is: there are several tasks in background calling FindOrCreate concurrently. I have prevented duplicates from being inserted by creating an unique index, but the following happens, causing unwanted exceptions:

  1. Task A tries to find Country and fails
  2. Task B tries to find Country and fails
  3. Task A tries to create Country and succeeds
  4. Task B tries to create Country and fails

What would be the appropriate way of handling these scenarios of concurrency? Should I work with locks using C# code? Or should I set a transaction? TIA

Upvotes: 2

Views: 1677

Answers (1)

Alex Buyny
Alex Buyny

Reputation: 3185

Handling concurrency at the DB level using unique index is the right approach here. Unique index will guarantee uniqueness of countries no matter what.

Don't bother locking the C# code, it will not work as soon as you've got more than 1 server running your app (these days it is likely). Transactions in this case are tricky business so I wouldn't bother.

How to handle those exceptions:

In case your task failed when creating country, catch the exception and retry. If you failed to get the country second time for some reason, log the exception and fail.

Upvotes: 6

Related Questions