Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何更新EntityFramework 6中附带子详细信息的父对象?_C#_Asp.net_Asp.net Mvc_Entity Framework_Asp.net Web Api - Fatal编程技术网

C# 如何更新EntityFramework 6中附带子详细信息的父对象?

C# 如何更新EntityFramework 6中附带子详细信息的父对象?,c#,asp.net,asp.net-mvc,entity-framework,asp.net-web-api,C#,Asp.net,Asp.net Mvc,Entity Framework,Asp.net Web Api,我有一个使用EF6的SPA ASP.NET WebAPI应用程序。应用程序有两个父-子实体,我在更新时遇到问题。代码的目的是,当用户更改前端代码时,目标及其详细信息将发送给控制器。然后,控制器检查是否有任何细节已更改,并处理这些细节。现在,我已经注释掉了这部分代码,因为我甚至无法获得最简单的更新。以下是我得到的错误: {“附加'Entities.Models.Core.ObjectiveDetail'类型的实体” 失败,因为相同类型的另一个实体已具有相同的 主键值。使用“附加”方法或 将实体的状

我有一个使用EF6的SPA ASP.NET WebAPI应用程序。应用程序有两个父-子实体,我在更新时遇到问题。代码的目的是,当用户更改前端代码时,目标及其详细信息将发送给控制器。然后,控制器检查是否有任何细节已更改,并处理这些细节。现在,我已经注释掉了这部分代码,因为我甚至无法获得最简单的更新。以下是我得到的错误:

{“附加'Entities.Models.Core.ObjectiveDetail'类型的实体” 失败,因为相同类型的另一个实体已具有相同的 主键值。使用“附加”方法或 将实体的状态设置为“未更改”或“已修改”(如果有) 图中的实体具有冲突的键值。这可能是因为 有些实体是新的,尚未收到生成的数据库 键值。在这种情况下,使用“添加”方法或“添加”实体 状态跟踪图形,然后将非新实体的状态设置为 “未更改”或“已修改”(视情况而定)。”

以下是我的两个课程:

public class Objective
{
    public Objective()
    {
        this.ObjectiveDetails = new HashSet<ObjectiveDetail>();
    }
    public int ObjectiveId { get; set; }
    public string Text { get; set; }
    public virtual ICollection<ObjectiveDetail> ObjectiveDetails { get; set; }
}

public partial class ObjectiveDetail
{
    public int ObjectiveDetailId { get; set; }
    public int ObjectiveId { get; set; }
    public string Text { get; set; }
    public virtual Objective Objective { get; set; }
}
然后我可以对数据库进行更新。如果我在这一行中添加(稍后需要添加),那么我将得到异常


有人能给我一些关于我做错了什么的建议吗?

您对注释行所做的是在
DbContext
中加载db实体。然后,您尝试再次将相同的实体附加到上下文,因此会出现冲突

您可以尝试在不同的上下文中加载旧实体,并将它们用作引用,以避免这种冲突

另一种解决方案是修改已经加载的实体(那些属于
oldObj
),它们已经在您的上下文中,而不是尝试再次添加具有不同状态的相同实体

也可以拆离或直接加载拆离的旧对象

理想情况下,您应该在水疗中心进行变更跟踪。这样,您就不需要加载旧实体并将它们与新实体进行比较。使用您的方法,应用程序可能会意外地写下其他人的更改

此代码:

var oldObj = db.ObjectiveDetails.Where(t => t.ObjectiveId == id).ToList();
加载数据库中的所有objectiveDetails并将其附加到当前上下文

此代码附加更新的目标详细信息,当已经有一个对象(在前一行代码中加载的对象)具有相同的键时,尝试附加一个对象(修改的对象):


这就是您在上下文中遇到冲突的方式。

我真的很想修改,但由于目标详细信息是来自浏览器的有效负载的一部分,我以前遇到过问题,因为EF似乎不了解添加了一些新的目标详细信息,有些可能被删除,有些可能被修改。请尝试其他选项:在不同的DbContext中加载旧对象。它们将不在同一上下文中,您将避免冲突,并且它们将可供参考以获取所接收实体的状态。理想情况下,SPA应该跟踪每个实体的状态,只在额外属性中发布aded/deelted/modified及其状态,这样您就不需要加载旧对象来获取状态。我在回答中添加了另一个选项感谢您的链接和建议。我发现,AsNoTracking()很有效。现在我想知道如何修改oldObj。我有旧的目标图和新的目标图。我注意到我的上下文有Configuration.AutoDetectChangesEnabled=false;如果我将此设置为true,您是否认为更新不仅会更新目标,还会更新其中包含的ObjectiveDetails?
var oldObj = db.ObjectiveDetails.Where(t => t.ObjectiveId == id).ToList();
var oldObj = db.ObjectiveDetails.Where(t => t.ObjectiveId == id).ToList();
foreach (var objectiveDetail in upd)
{
   db.Entry(objectiveDetail).State = EntityState.Modified;
}