entity-framework - EF Core 3.x:重复值
问题描述
我有以下代码:
public class DeviceVerizon
{
public int DeviceId { get; set; }
public string InternalDeviceId { get; set; }
}
和
public class DeviceVerizonMap : IEntityTypeConfiguration<DeviceVerizon>
{
public void Configure(EntityTypeBuilder<DeviceVerizon> builder)
{
builder.ToTable(nameof(DeviceVerizon));
builder.HasKey(d => d.DeviceId);
builder.HasIndex(v => v.InternalDeviceId).IsUnique();
builder.HasOne(o => o.Device)
.WithOne(o => o.VerizonData)
.HasForeignKey<DeviceVerizon>(a => a.DeviceId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
;
}
}
所以,InternalDeviceId 只是唯一索引。
一些代码更改现有记录的 InternalDeviceId 并使用以前的 InternalDeviceId 添加新记录。所以,localDevice.VerizonData.InternalDeviceId = 1420531689
我将其更新为新的 ( remoteDevice.VerizonData.InternalDeviceId = '111111111'
)
localDevice.VerizonData = remoteDevice.VerizonData;
_context.Devices.Update(localDevice);
然后添加新记录remoteDevice.VerizonData.InternalDeviceId = 1420531689
:
_context.Devices.Add(remoteDevice);
之后我打电话:
await _context.SaveChangesAsync();
但我得到一个例外:
无法在具有唯一索引“IX_DeviceVerizon_InternalDeviceId”的对象“dbo.DeviceVerizon”中插入重复的键行。重复键值为 (1420531689)。
完整代码:
foreach (var remoteDevice in remoteVerizonDevices)
{
var localDevice = allLocalDevicesWithIMEI.Where(a =>
(string.IsNullOrWhiteSpace(remoteDevice.IMEI)
&& a.VerizonData != null
&& a.VerizonData.InternalDeviceId == remoteDevice.VerizonData.InternalDeviceId
&& a.IMSI == remoteDevice.IMSI && a.ICCID == remoteDevice.ICCID)
|| a.IMEI == remoteDevice.IMEI).FirstOrDefault();
if (localDevice != null) // device with such imei already exists or IMEI is empty on Verizon, but InternalDeviceId is the same and ICCID with IMSI are the same
{
var verizonStatus = remoteDevice.VerizonData.State.ConvertToDeviceStatusFromVerizonStatus();
var existingRequest = _context.VerizonRequests.Where(a => a.DeviceId == localDevice.Id && a.Result == VerizonRequestResult.Pending).FirstOrDefault();
if (verizonStatus == DeviceStatus.Active && remoteDevice.IsVerizonLastActiveMoreThanDays(60))
{
// existing request for this device does not exist, create new
if (existingRequest == null)
{
localDevice.Status = DeviceStatus.PendingSuspend;
localDevice.DateStatusChanging = DateTime.UtcNow;
localDevice.LastStatusChangeSource = DeviceStatusChangeSource.Verizon;
// create verizon request to change status, because device is offline more than 60 days
verizonSuspensionList.Add(localDevice.Id);
}
}
else
{
// Is Verizon status of device is different than locally?
if (localDevice.Status != verizonStatus)
{
// check whether we have active verizon request, if not, then
if (existingRequest == null)
{
// device is suspended on suremdm, we should suspend on Verizon
if (localDevice.Status == DeviceStatus.Suspended
&& verizonStatus == DeviceStatus.Active)
{
if (localDevice.Tablet != null && localDevice.Tablet.TabletGroup.GroupName == SpecialSureMdmGroups.Suspended)
verizonSuspensionList.Add(localDevice.Id);
}
else if (localDevice.Status != DeviceStatus.Suspended && verizonStatus == DeviceStatus.Suspended)
{
// if device is suspended on verizon, we need to suspend on SureMdm
localDevice.Status = DeviceStatus.PendingSuspend;
localDevice.DateStatusChanging = DateTime.UtcNow;
localDevice.LastStatusChangeSource = DeviceStatusChangeSource.Verizon;
if (localDevice.Tablet != null)
{
localDevice.Tablet.SuspensionDate = DateTime.UtcNow;
sureMdmSuspensionList.Add(new Core.Dto.DeviceManagement.SureMdm.SureMdmMoveDeviceToSuspendedGroupDto
{
TabletId = localDevice.Tablet.TabletId,
CurrentGroupId = localDevice.Tablet.TabletGroupId
});
}
}
else
{
// other cases that device on verizon has different status, that locally
VerizonStatusIsDifferentEvent?.Invoke(
remoteDevice: remoteDevice,
verizonStatus: remoteDevice.VerizonData.State.ConvertToDeviceStatusFromVerizonStatus(),
localStatus: localDevice.Status);
}
}
}
}
var changes = DeviceIsChanged(remoteDevice, localDevice);
if (changes != null && changes.Count > 0)
modifiedDevices.Add((localDevice, changes));
var continueToUpdate = true;
// if verizon data does not exist, add it
if (localDevice.VerizonData == null)
{
var existingInternalVerizonDeviceIdRecord = allDeviceVerizons.Where(a => a.InternalDeviceId == remoteDevice.VerizonData.InternalDeviceId).FirstOrDefault();
if (existingInternalVerizonDeviceIdRecord != null)
{
DeviceWithTheSameVerizonDeviceIdAlreadyExistsEvent?.Invoke(remoteDevice: remoteDevice,
localDevice: existingInternalVerizonDeviceIdRecord.Device,
verizonDeviceId: remoteDevice.VerizonData.InternalDeviceId);
continueToUpdate = false;
}
}
if (continueToUpdate)
{
localDevice.VerizonData = remoteDevice.VerizonData;
if (!string.IsNullOrWhiteSpace(remoteDevice.ICCID))
localDevice.ICCID = remoteDevice.ICCID;
localDevice.EID = remoteDevice.EID;
localDevice.ESN = remoteDevice.ESN;
if (!string.IsNullOrWhiteSpace(remoteDevice.IMSI))
localDevice.IMSI = remoteDevice.IMSI;
if (!string.IsNullOrWhiteSpace(remoteDevice.MDN))
localDevice.MDN = remoteDevice.MDN;
localDevice.MEID = remoteDevice.MEID;
localDevice.MIN = remoteDevice.MIN;
localDevice.MSISDN = remoteDevice.MSISDN;
localDevice.SKU = remoteDevice.SKU;
localDevice.SyncVerizon = true;
if (string.IsNullOrWhiteSpace(localDevice.Name))
localDevice.Name = localDevice.IMEI;
if (!localDevice.DeviceModelId.HasValue)
{
var verizonGroup = allVerizonGroups.Where(a => a.VerizonGroupName == remoteDevice.VerizonData.GroupName).FirstOrDefault();
if (!verizonGroup.DeviceModelId.HasValue)
VerizonGroupIsNotLinkedWithDeviceModelEvent?.Invoke(remoteDevice);
else
localDevice.DeviceModelId = verizonGroup.DeviceModelId;
}
_context.Devices.Update(localDevice);
}
}
else
{
// validate by Internal Verizon DeviceId
var existingInternalVerizonDeviceIdRecord = allDeviceVerizons.Where(a => a.InternalDeviceId == remoteDevice.VerizonData.InternalDeviceId).FirstOrDefault();
if (existingInternalVerizonDeviceIdRecord != null)
{
DeviceWithTheSameVerizonDeviceIdAlreadyExistsEvent?.Invoke(remoteDevice: remoteDevice,
localDevice: existingInternalVerizonDeviceIdRecord.Device,
verizonDeviceId: remoteDevice.VerizonData.InternalDeviceId);
}
else
{
// add new record
if (!string.IsNullOrWhiteSpace(remoteDevice.IMEI))
remoteDevice.Name = remoteDevice.IMEI;
else if (!string.IsNullOrWhiteSpace(remoteDevice.VerizonData.PrimaryPlaceOfUseFirstName) || !string.IsNullOrWhiteSpace(remoteDevice.VerizonData.PrimaryPlaceOfUseLastName))
remoteDevice.Name = $"{remoteDevice.VerizonData.PrimaryPlaceOfUseFirstName} {remoteDevice.VerizonData.PrimaryPlaceOfUseLastName}";
else
remoteDevice.Name = Core.Constants.Common.Undefined;
// set device Model
var verizonGroup = allVerizonGroups.Where(a => a.VerizonGroupName == remoteDevice.VerizonData.GroupName).FirstOrDefault();
if (!verizonGroup.DeviceModelId.HasValue)
VerizonGroupIsNotLinkedWithDeviceModelEvent?.Invoke(remoteDevice);
else
remoteDevice.DeviceModelId = verizonGroup.DeviceModelId;
// set device status
remoteDevice.Status = remoteDevice.VerizonData.State.ConvertToDeviceStatusFromVerizonStatus();
if (!string.IsNullOrWhiteSpace(remoteDevice.VerizonData.CarrierName))
{
var verizonCarrier = allVerizonCarriers.Where(a => a.VerizonCarrierName == remoteDevice.VerizonData.CarrierName).FirstOrDefault();
if (verizonCarrier.CarrierId.HasValue)
remoteDevice.CarrierId = verizonCarrier.CarrierId;
else
{
// notify that carrier is not found locally
LocalCarrierIsNotFoundForNewDeviceEvent?.Invoke(remoteDevice);
}
}
remoteDevice.SyncVerizon = true;
_context.Devices.Add(remoteDevice);
newDevices.Add(remoteDevice);
}
}
}
await _context.SaveChangesAsync();
为什么这样?只有一条记录有 1420531689,旧的已更新为新值(111111111)并保存在一个事务中......如何正确执行?
解决方案
推荐阅读
- express - 在 flash() 之后立即重定向时出现 express.js 错误
- dart - 如何在 Dart 2.x 中进行 BigInt 算术,特别是除法?
- python - 选择具有 NaN 或 NULL 值的 pandas 数据框列并用 0 填充
- c# - 如何在数组[][,]和[,][]中输入和输出值(交错数组和多维数组的混合)
- javascript - 使用 push 将 JS 对象插入数组在某些上下文中不起作用
- python - Python subprocess.Popen()未运行命令
- python-3.x - 滚动条未显示 - tkinter
- python - 在 pyqt5 中对齐小部件中的按钮时出现问题
- android - 在mapbox中,当我点击android上的按钮时如何返回我的位置
- javascript - action="javascript:void(0) 时提交表单