I have many scenarios when I need to update data of an existing record by criteria or create a new record with this data.
For example, I have an entity.
public class UserStateEntity
{
public Guid Id { get; set; }
public string UserName { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
I need to store values by user and key. Now I use code like this:
public async Task AddCacheValueAsync(string userName, string key, string value)
{
var existedData = await dbContext.UserCache.SingleOrDefaultAsync(d => d.UserName == userName && d.Key == key);
if (existedData != null)
existedData.Value = value;
else
{
var userData = new UserStateEntity
{
UserName = userName,
Key = key,
Value = value
};
dbContext.UserCache.Add(userData);
}
await dbContext.SaveChangesAsync();
}
Is there a better way to find an existing record or create a record during updating cache value? I thought about something like this:
dbContext.UserCache.Upsert(d => d.UserName == userName && d.Key == key, d => {
d.UserName = userName;
d.Key = key;
d.Value = value;
});
or like this:
dbContext.UserCache.Upsert(
/* entity for compare or creation */ d => new UserStateEntity { d.UserName = userName, d.Key == key },
/* updating fields */ d => d.Value = value);
I tried FlexLabs.Upsert
library, but it always insert a new row instead of updating an existing one:
public async Task UpdateStateAsync()
{
var userData = new UserStateEntity
{
UserName = "123",
Key = "456",
Value = "MainMenu"
};
await dbContext
.UserData
.Upsert(userData)
.On(ud => new {ud.UserName, ud.Key})
.WhenMatched(v => new UserDataEntity {Value = userData.Value})
.RunAsync();
await dbContext.SaveChangesAsync();
}
this code generates following SQL query for my MySql database:
INSERT INTO `bot.user_data` (`key`, `user_name`, `value`)
VALUES ('456', '123', 'MainMenu')
ON DUPLICATE KEY UPDATE `value` = 'MainMenu'