实体框架5更新时出错:数据可能已被修改



这是我的实体框架存储库:

public class MetricRepository : IMetricRepository
{
private readonly AccountStatsContext _context;
public MetricRepository(AccountStatsContext context)
{
_context = context;
}
public async Task<bool> Add(MetricEntity metric)
{
metric.UpdatedOnUtc = DateTime.UtcNow;
await _context.Metrics.AddAsync(metric).ConfigureAwait(false);
await _context.SaveChangesAsync().ConfigureAwait(false);
return true;
}
public async Task<bool> Update(MetricEntity metric)
{
metric.UpdatedOnUtc = DateTime.UtcNow;
await _context.SaveChangesAsync();
return true;
}
public async Task<MetricEntity> FindAsync(Expression<Func<MetricEntity, bool>> predicate)
{
return await _context.Metrics.SingleOrDefaultAsync(predicate);
}
}

在我的表中,我有一个包含4列的复合主键,如下所示:

CREATE TABLE public.metrics
(
category character (30) COLLATE pg_catalog."default" NOT NULL,
code character (30) COLLATE pg_catalog."default" NOT NULL,
repartition_key character (30) COLLATE pg_catalog."default" NOT NULL,
date timestamp without time zone NOT NULL,
value numeric(18,2),
type character (5) COLLATE pg_catalog."default" NOT NULL,
updated_on_utc timestamp without time zone NOT NULL,
CONSTRAINT metrics_pkey PRIMARY KEY (category, code, repartition_key, date)
);

主键设置在我的实体框架存储库中

private void BuildEntity(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MetricEntity>()
.ToTable("metrics")
.HasKey(c => new { c.Category, c.Code, c.RepartitionKey, c.Date });
}

当我插入时,它是可以的,但当我尝试更新一个值时,我会得到这个错误:

数据库操作预计影响1行,但实际影响0行。自实体加载以来,数据可能已被修改或删除

这是我的更新代码:

public async Task<BaseResponse> Handle(MetricsCommand request, CancellationToken cancellationToken)
{
var requestMapped = _mapper.Map<MetricEntity>(request);
var result = await _metricRepository.FindAsync(m => m.Category == requestMapped.Category && m.Code == requestMapped.Code && m.RepartitionKey == requestMapped.RepartitionKey && m.Date == requestMapped.Date);
bool response = false;
if (result == null)
response = await _metricRepository.Add(requestMapped);
else
{
result.Value = requestMapped.Value;
result.Type = requestMapped.Type;
response = await _metricRepository.Update(result);
}
return new BaseResponse(response);
}

我总是用这个算法只更新几个属性,它从未失败过

var metric = _mapper.Map<MetricEntity>(request); //I hope your code works properly
var existedMetric = await _context.FindAsync(m => m.Category == requestMapped.Category && m.Code == requestMapped.Code && m.RepartitionKey == requestMapped.RepartitionKey && m.Date == requestMapped.Date);

if (existedMetric!=null)
{
context.Entry(existedMetric).Property(m=> m.Value ).CurrentValue = metric.Value;
context.Entry(existedMetric).Property(m=> m.Type).CurrentValue =  metric.Type;
context.Entry(existedMetric).Property(m=> m.UpdatedOnUtc).CurrentValue =  DateTime.UtcNow;
await _context.SaveChangesAsync();
}

使用数据库context的最佳方法是在使用之前和之后立即创建并处理它。但是,由于您已经在使用另一种方法,我只能假设以下代码可以帮助您。在MetricRepository类的Update方法中的metric.UpdatedOnUtc = DateTime.UtcNow;之后插入提供的行:

_context.Entry(metric).State = EntityState.Modified;

UPD:如果没有帮助,还有另一种方法可以修改dbcontext中的实体。将其插入与前一提示相同的位置:

_context.Update(metric);

像这样更改Generic Update方法。您应该将实体的状态设置为已修改

public async Task<bool> Update(MetricEntity metric)
{
metric.UpdatedOnUtc = DateTime.UtcNow;
_context.Entry(metric).State = EntityState.Modified; 
await _context.SaveChangesAsync();
return true;
}

最新更新