【发布时间】:2017-08-25 00:57:45
【问题描述】:
使用 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
我更新了如下代码并将状态显式设置为已修改
// 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”,因为此类型的另一个实例 已使用相同的密钥进行跟踪。添加新实体时, 对于大多数键类型,如果没有,将创建一个唯一的临时键值 键已设置(即,如果为键属性分配了默认值 它的类型)。如果您要为新实体显式设置键值, 确保它们不会与现有实体或临时值发生冲突 为其他新实体生成。附加现有实体时, 确保只有一个具有给定键值的实体实例 依附于上下文。在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey 键,InternalEntityEntry 条目)在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry 条目)在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges)
实体具有int 类型的Id 属性,并且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);
但这并没有刷新。
【问题讨论】:
-
您是否尝试过将实体状态标记为已修改?
_dbContext.Entry(entity).State = EntityState.Modified; -
@Steve _dbContext 如何匹配实例,_dbContext 如何知道将哪个实体标记为已修改?
标签: entity-framework entity-framework-6 entity-framework-core