【问题标题】:EF Core cannot update entity with two navigation properties to same object (other entity)EF Core 无法将具有两个导航属性的实体更新为同一对象(其他实体)
【发布时间】:2019-05-29 11:24:54
【问题描述】:

我有两张桌子。用户表有两个链接到另一个(相同的)实体,即语言:

public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Language OrigLanguage { get; set; }
    public Language Language { get; set; }
}

public class Language
{
    public int Id { get; set; }
    public string Name { get; set; }
}

EF 正确创建表:

表“用户”:Id、FirstName、LastName、LanguageId、OrigLanguageId

我可以为 OrigLanguage 和 Language 添加具有相同值的用户,而不会出现任何问题。 一旦我尝试使用相同的值更新现有用户,我就会收到以下错误消息:

InvalidOperationException:实体类型“语言”的实例 无法跟踪,因为另一个实例的键值为 '{Id: 1}' 已被跟踪。附加现有实体时,确保 仅附加一个具有给定键值的实体实例。

使用以下堆栈:

Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap.ThrowIdentityConflict(InternalEntityEntry 入口) Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap.Add(TKey 键,InternalEntityEntry 条目,bool updateDuplicate) Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry 入口) Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, bool acceptChanges) Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, bool acceptChanges, Nullable forceStateWhenUnknownKey) Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode 节点,布尔力) Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph(EntityEntryGraphNode 节点,TState 状态,Func 句柄节点) Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph(EntityEntryGraphNode 节点,TState 状态,Func 句柄节点) Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState entityState, bool forceStateWhenUnknownKey) Microsoft.EntityFrameworkCore.DbContext.SetEntityState(InternalEntityEntry 条目,EntityState 实体状态) Microsoft.EntityFrameworkCore.DbContext.SetEntityState(TEntity 实体,实体状态实体状态) Microsoft.EntityFrameworkCore.DbContext.Attach(TEntity 实体) Namespace.Data.Repository.UpdateAsync(T entity) in Repository.cs

在我的 Startup.cs 中,我有以下设置来防止跟踪:

services.AddDbContext<DocLogDBContext>(
    options => options.UseSqlServer(...)
    .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)

在我的存储库中,我有以下代码要更新:

public override async Task<User> UpdateAsync(User entity)
{
    // below two detachments have no effect
    _context.Attach(entity.OrigLanguage).State = EntityState.Detached;
    _context.Attach(entity.Language).State = EntityState.Detached;
    _context.Attach(entity).State = EntityState.Modified;
    await _context.SaveChangesAsync();
    return entity;
}

我的 API 控制器如下所示:

[HttpPost]
public virtual async Task<IActionResult> Edit(T model)
{
    await _repository.UpdateAsync(model);
    return Ok(model);
}

这是来自客户端的请求:

Request URL: https://localhost:44344/api/User/Edit
Request Payload: 
{
    Id: 3
    , FirstName: "Joe"
    , LastName: "Frazer"
    , Language: { Name: "english", ShortName: "en", Id: 1 }
    , OrigLanguage: { Name: "english", ShortName: "en", Id: 1 }
}

我在这里错过了什么?

【问题讨论】:

    标签: c# entity-framework .net-core


    【解决方案1】:

    我们可以通过在 poco 类上使用 "[ForeignKey("xxxxx")]" 属性来解决。 在这里,我正在尝试更正如下代码:

       public class User
       {
           public int Id { get; set; }
           public string FirstName { get; set; }
           public string LastName { get; set; }
           [ForeignKey("OrigLanguage")]
           public int OrigLanguageId { get; set; }
           [ForeignKey("Language")]
           public int LanguageId { get; set; }
    
           public Language OrigLanguage { get; set; }
           public Language Language { get; set; }
       }
    

    【讨论】:

    • 太棒了!非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 2014-12-03
    • 1970-01-01
    • 2023-04-09
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多