Похоже, что EF Core делает INSERT вместо UPDATE, и поэтому MySQL жалуется на дубликат ключа. Тем не менее, я использую метод Update на DbSet, и у сущностей установлены первичные ключи. Это приводит к ошибке DUPLICATE ENTRY в MySql.
Запуск VS 2019, EF Core 3.1.1 и ASP. NET Core 3.1
* Модель 1007 * (я не использую конфигурацию Fluent для отношений, просто конвенция):
public class Vehicle
{
public long Id {get; set; } // PRIMARY KEY, AUTO INCREMENT
public string RegistrationNumber { get; set; }
public VehicleSession Session { get; set; }
}
public class VehicleSession
{
public long VehicleId { get; set; }
public Vehicle Vehicle { get; set; }
public string DeviceUuid { get; set; } // PRIMARY KEY
public string AuthenticationToken { get; set; }
public string OSName { get; set; }
public string OSVersion { get; set; }
public string DeviceModel { get; set; }
}
База данных:
Таблица «Тезисы», где ПЕРВИЧНЫЙ KEY является DeviceUuid и имеет ключ 'device2':

Контроллер:
Запрос поступает от где-то. DeviceUuid извлекается из заголовков HTTP.
public async Task<ActionResult<VehicleLoginResponse>> Login(VehicleLogin login)
{
Request.Headers.TryGetValue(BaseConstants.DEVICE_UUID, out StringValues deviceUuid);
Vehicle vehicle = await vehicleService.Authenticate(login.Username, login.Password); // returns a Vehicle by asking dbContet: dbContext.Vehicles.FirstOrDefault(v => v.Username.Equals(username));
VehicleSession vs = await vehicleService.CreateSession(vehicle, login, deviceUuid);
// ...
}
Служба:
Эта служба создает новый объект VehicleSession, назначает его свойству Vehicle и выполняет .Update. на транспортном средстве, так что новый сеанс сохраняется вместе с ним.
public async Task<VehicleSession> CreateSession(Vehicle vehicle, VehicleLogin vehicleLogin, string deviceUuid)
{
VehicleSession vs = new VehicleSession()
{
Vehicle = vehicle,
AuthenticationToken = someTokenFetchedFromSomewhere,
DeviceModel = vehicleLogin.DeviceModel,
DeviceUuid = deviceUuid, // is 'device2'
OSName = vehicleLogin.OSName,
OSVersion = vehicleLogin.OSVersion
};
vehicle.Session = vs;
dbContext.Vehicles.Update(vehicle);
await dbContext.SaveChangesAsync();
return vs;
}
Не имеет значения, если я заменю new VehicleSession
и назначение, просто редактируя уже существующий Vehicle.Session, та же ошибка :
public async Task<VehicleSession> CreateSession(Vehicle vehicle, VehicleLogin vehicleLogin, string deviceUuid)
{
if (vehicle.Session == null)
vehicle.Session = new VehicleSession(); // never executes this line
vehicle.Session.AuthenticationToken = someTokenFetchedFromSomewhere;
vehicle.Session.DeviceModel = vehicleLogin.DeviceModel;
vehicle.Session.DeviceUuid = deviceUuid;
vehicle.Session.OSName = vehicleLogin.OSName;
vehicle.Session.OSVersion = vehicleLogin.OSVersion;
await dbContext.SaveChangesAsync();
return vehicle.Session;
}
При этом я получаю сообщение об ошибке:
Microsoft.EntityFrameworkCore.DbUpdateException: при обновлении записей произошла ошибка. Смотрите внутреннее исключение для деталей. ---> MySql .Data.MySqlClient. 'for key' vehiclesessions.PRIMARY '
Произошло SQL:
Failed executing DbCommand (125ms) [Parameters=[@p0='?' (Size = 95), @p1='?' (Size = 95), @p2='?' (Size = 4000), @p3='?' (Size = 4000), @p4='?' (Size = 4000), @p5='?' (DbType = Int64)], CommandType='Text', CommandTimeout='30']
INSERT INTO `VehicleSessions` (`DeviceUuid`, `AuthenticationToken`, `DeviceModel`, `OSName`, `OSVersion`, `VehicleId`)
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
fail: Microsoft.EntityFrameworkCore.Update[10000]
An exception occurred in the database while saving changes for context type 'blabla'.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Duplicate entry 'device2' for key 'vehiclesessions.PRIMARY'
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Duplicate entry 'device2' for key 'vehiclesessions.PRIMARY'
Почему я получаю эту ошибку? Кажется, что INSERT выполняется вместо UPDATE, даже если объект Vehicle получен из dbContext, передан и имеет установленный PRIMARY id.