相同的键值已经被跟踪

6
System.InvalidOperationException: The instance of entity type 'ProjectAssignment' cannot be tracked because another instance with the same key value for {'ProjectID'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.St

我使用Worker(ID和其他列)和Project(ID和其他列)实体以及ProjectAssignment(多个Project ID对应多个Workers)交叉绑定创建了一个项目。但是,当我尝试获取ProjectAssignment数据时,在Application Insights中出现错误。奇怪的是之前没有显示id。
这里是链接:https://github.com/Streamc/ContosoObserve1/tree/master/Proj_s
 context.Database.EnsureCreated();

  var ProjectAssignments = new ProjectAssignment[]
             {
                    new ProjectAssignment
                    {
                        ProjectID = Projects.Single( i => i.ID == 1).ID,
                        WorkerID = Workers.Single( i => i.ID == 1).ID,
                    },
                     new ProjectAssignment
                    {
                        ProjectID = Projects.Single( i => i.ID == 1).ID,
                        WorkerID = Workers.Single( i => i.ID == 2).ID,
                    },
                     new ProjectAssignment
                    {
                        ProjectID = Projects.Single( i => i.ID == 1).ID,
                        WorkerID = Workers.Single( i => i.ID == 3).ID,
                    },
                    new ProjectAssignment
                    {
                        ProjectID = Projects.Single( i => i.ID == 2).ID,
                        WorkerID = Workers.Single( i => i.ID == 1).ID,
                    },
                    new ProjectAssignment
                    {
                        ProjectID = Projects.Single( i => i.ID == 3).ID,
                        WorkerID = Workers.Single( i => i.ID == 1).ID,
                    },
                    new ProjectAssignment
                    {
                        ProjectID = Projects.Single( i => i.ID == 4).ID,
                        WorkerID = Workers.Single( i => i.ID == 1).ID,
                    },
                    new ProjectAssignment
                    {
                        ProjectID = Projects.Single( i => i.ID == 2).ID,
                        WorkerID = Workers.Single( i => i.ID == 2).ID,
                    },
                    new ProjectAssignment
                    {
                        ProjectID = Projects.Single( i => i.ID == 2).ID,
                        WorkerID = Workers.Single( i => i.ID == 3).ID,
                    },
                    new ProjectAssignment
                    {
                        ProjectID = Projects.Single( i => i.ID == 2).ID,
                        WorkerID = Workers.Single( i => i.ID == 4).ID,
                    }

             };
            foreach (ProjectAssignment ss in ProjectAssignments)
            {
                context.ProjectAssignments.Add(ss);
            }
            context.SaveChanges();



 public class ProjectAssignment
    {
        [Key]
        public int ProjectID { get; set; }
        public int WorkerID { get; set; }


        public Project Project { get; set; }
        public Worker Worker { get; set; }

    }
   public class Worker
    {
        public int ID { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public string Fathername { get; set; }
        public string email { get; set; }    
        public string Company_name { get; set; }
        public ICollection<ProjectAssignment> ProjectAssignment { get; set; }

    }
    public class Project
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Customer_Company { get; set; }
        public string Executive_Company { get; set; }
        public int ManagerID { get; set; }    
        public int WorkerID { get; set; }    
        public DateTime Begin_date { get; set; }
        public DateTime End_date { get; set; }
        public int Priority { get; set; }    
        public string Test_comment { get; set; }    
        public ICollection<ProjectAssignment> ProjectAssignment { get; set; }
    }

2
请提供一些能够重现此错误的代码。请参考[mcve]以获取创建良好代码示例的提示。 - Code-Apprentice
1个回答

12

请仔细阅读错误信息:

实体类型 'ProjectAssignment' 的实例无法被跟踪,因为另一个实例已经使用相同的 {'ProjectID'} 键值进行跟踪。

因此,问题在于我们有两个或更多具有相同 ProjectIDProjectAssignment

如果我们查看代码,会发现我们将相同的 ProjectID 分配了两次:

 var ProjectAssignments = new ProjectAssignment[] {
     new ProjectAssignment {
         ProjectID = Projects.Single( i => i.ID == 1).ID, // ID == "1"
         WorkerID = Workers.Single( i => i.ID == 1).ID,
     },
     new ProjectAssignment {
         ProjectID = Projects.Single( i => i.ID == 1).ID, // ID == "1", again
         WorkerID = Workers.Single( i => i.ID == 2).ID,
     },
     // ...
 }

根本原因似乎是将 ProjectID 建模为主键而不是外键。主键必须是唯一的。您可能想要的是由ProjectIDWorkerID组成的复合主键

查看您的 Github 项目中的 ProjectContext,这个复合主键已经存在:

modelBuilder.Entity<ProjectAssignment>().HasKey(c => new { c.ProjectID, c.WorkerID });

但它与ProjectAssignment.ProjectID上的[Key]注释冲突。移除此[Key]属性!


我找到了它。我进行了修复。是的,逻辑是二列键。我刚刚测试了keyattribute并错过了没有删除行。问题确实出在键属性上。谢谢回答! - streamc
我认为这个问题应该被删除。 - streamc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接