使用Entity Framework Core我试图为同一个实体集合保存两次更改。
public async Task Save(IEnumerable<Request> request)
{
var entities = request.Select(x => new MyEntity()
{
FileName = x.FileName,
Status = Status.Downloading
});
// save as downloading
await _dbContext.MyFiles.AddRangeAsync(entities).ConfigureAwait(false);
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
// start downloading
await _storage.DownloadFilesAsync(request).ConfigureAwait(false);
// save as downloaded
foreach (var entity in entities)
{
entity.Status = Status.Downloaded;
}
// this save DOES NOT update the entities with status Downloaded
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
}
第一次调用SaveChanges()
方法会在数据库中创建状态为Downloading
的实体。
然后我将实体的状态修改为Downloaded
并再次致电SaveChanges()
。但是,这次实体不会在DB中更新。
我认为实体已经在Db上下文中加载,所以我不必在第二个SaveChanges
之前重新加载它们。只修改属性会标记它们被修改。但它不起作用。
更新1
我更新了如下代码并明确将State设置为Modified
// save as downloaded
foreach (var entity in entities)
{
entity.Status = Status.Downloaded;
// The exception occurs at line below on 2nd loop
_dbContext.Entry(entity).State = EntityState.Modified;
}
现在我得到了异常
System.InvalidOperationException:实体类型的实例 无法跟踪“MyEntity”,因为此类型的另一个实例 已经跟踪了相同的密钥。添加新实体时, 对于大多数密钥类型,如果不是,将创建唯一的临时密钥值 key被设置(即,如果为key属性分配了默认值 它的类型)。如果您明确设置新实体的键值, 确保它们不会与现有实体或临时值发生冲突 为其他新实体生成。附加现有实体时, 确保只有一个具有给定键值的实体实例 附在上下文中。在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKEY的 key,InternalEntityEntry条目)at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry 进入) Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState,EntityState newState,Boolean acceptChanges)
该实体具有Id
类型的int
属性,Id
属性也具有[Key]
属性。
public class MyEntity
{
[System.ComponentModel.DataAnnotations.Key]
public int Id {get;set;}
public string FileName {get;set;}
public string Status {get;set;}
}
更新2
因此,在进行了一些调试后,我发现第一个SaveChanges()
操作是在数据库中创建记录,并按预期为每个记录分配唯一的ID。 Id
是数据库中自动递增的标识列。
但是,实体不会刷新新的ID。所以所有实体在第一次保存更改后仍然具有值0。
如何使用新创建的ID刷新这些实体?
在foreach
循环中,我尝试重新加载为
_dbContext.Entry<OcrFile>(entity).ReloadAsync().ConfigureAwait(false);
但是没有刷新。
答案 0 :(得分:1)
解决!!。我必须先使用ToList()
或ToArray()
加载实体,然后再将其传递给AddRange
方法
var entities = request.Select(x => new MyEntity()
{
FileName = x.FileName,
Status = Status.Downloading
}).ToList();
我不确定这是EF中的错误但我为该问题创建了单独的SO thread