I wrote an InsertOrUpdate()
method which uses my EntityFramework dbcontext and I want the method to be able to receive an object and then either insert a new row or update an existing one if it exists already. Inserting works fine but unfortunately, EF won't let me do that for the update. It actually pretends it has worked but then, after reading the row, I see it didn't change.
public async Task<bool> InsertOrUpdateUserByExternalId(UserModel user, CancellationToken cancellationToken = default)
{
if(user.User_ExternalID is null)
return false;
var userInDb = (await _db.Users
.AsNoTracking()
.FirstOrDefaultAsync(
u => u.User_ExternalID == user.User_ExternalID,
cancellationToken))
.Adapt<UserModel>();
if (userInDb is not null)
{
user.User_ExternalID = null; // Without this I get a "duplicate index" error
userInDb = user;
_db.Users.Update(userInDb.Adapt<User>());
}
else
{
await _db.Users.AddAsync(user.Adapt<User>(), cancellationToken);
}
var changes = _db.SaveChanges(); // This returns 1 which seems like it was successful
return changes == 1;
}
In this version I don't convert the row from the database to a model but instead work with the entity and convert the user from the parameter to an entity. Unfortunately, I get the same outcome.
public async Task<bool> InsertOrUpdateUserByExternalId(UserModel user, CancellationToken cancellationToken = default)
{
if (user.User_ExternalID is null)
return false;
var userInDb = (await _db.Users
.AsNoTracking()
.FirstOrDefaultAsync(
u => u.User_ExternalID == user.User_ExternalID,
cancellationToken));
if (userInDb is not null)
{
user.User_ExternalID = null;
userInDb = user.Adapt<User>();
_db.Users.Update(userInDb);
}
else
{
await _db.Users.AddAsync(user.Adapt<User>(), cancellationToken);
}
var changes = _db.SaveChanges();
return changes == 1;
}