【问题标题】:Multiple added entities may have the same primary key多个添加的实体可能具有相同的主键
【发布时间】:2011-08-27 19:36:39
【问题描述】:

这是我的 3 个实体模型:Route、Location 和 LocationInRoute。

以下方法在提交时失败并得到异常:

 public static Route InsertRouteIfNotExists(Guid companyId, IListLocation> locations)
        {
            //Loop on locations and insert it without commit
            InsertLocations(companyId, routesOrLocations);

            RouteRepository routeRep = new RouteRepository();
            Route route = routeRep.FindRoute(companyId, locations);
            if (route == null)
            {
                route = new Route()
                {
                    CompanyId = companyId,
                    IsDeleted = false
                };
                routeRep.Insert(route);
                LocationInRouteRepository locInRouteRep = new LocationInRouteRepository();
                for (int i = 0; i < locations.Count; i++)
                {
                    locInRouteRep.Insert(new LocationInRoute()
                    {
                        //Id = i,
                        LocationId = locations[i].Id,
                        Order = i,
                        RouteId = route.Id
                    });
                }
            }
            return route;
        }

做的时候:

InsertRouteIfNotExists(companyId, locations);
UnitOfWork.Commit();

我明白了:

无法确定“SimTaskModel.FK_T_STF_SUB_LOCATION_IN_ROUTE_T_STF_LOCATION_location_id”关系的主体端。多个添加的实体可能具有相同的主键。

当拆分提交并插入到方法中时 - 它可以工作:

  public static Route InsertRouteIfNotExists(Guid companyId, IListLocation> locations)
            {
                //Loop on locations and insert it without commit
                InsertLocations(companyId, routesOrLocations);
                UnitOfWork.Commit();

                RouteRepository routeRep = new RouteRepository();
                Route route = routeRep.FindRoute(companyId, locations);
                if (route == null)
                {
                    route = new Route()
                    {
                        CompanyId = companyId,
                        IsDeleted = false
                    };
                    routeRep.Insert(route);
                    LocationInRouteRepository locInRouteRep = new LocationInRouteRepository();
                    for (int i = 0; i < locations.Count; i++)
                    {
                        locInRouteRep.Insert(new LocationInRoute()
                        {
                            //Id = i,
                            LocationId = locations[i].Id,
                            Order = i,
                            RouteId = route.Id
                        });
                    }
                    UnitOfWork.Commit();
                }
                return route;
            }

我想在方法之外调用一次提交。为什么它在第一个示例中失败,这个异常意味着什么?

【问题讨论】:

  • @Ladislav Mrnka:我没有老板,这是我的项目。我真的不知道您从哪里得到我立即询问 SO 的印象。你不是唯一一个整天使用电脑的人。免费咨询?有人会保证他的答案吗?我相信这是一个可以在这里提问的论坛,这就是我正在做的事情。我有很多问题,我相信感谢这个论坛和像你这样的人,我做了很长的学习。参与是一种选择。
  • @Ladislav:我只看到一个问得相当好的问题,而且 OP 的个人资料也没有表明任何内容。
  • 您是在整个操作范围内使用相同的 ObjectContext,还是每个新的存储库都有自己的 ObjectContext?
  • @Akash Kava:我使用的是同一个 ObjectContext。

标签: c# .net entity-framework


【解决方案1】:

错误是由无法解析的外键 ID(而不是引用)引起的。在您的情况下,您有一个 LocationInRole 引用 ID 为 0 的位置。有多个具有此 ID 的位置。

位置尚未分配 ID,因为它们尚未保存到生成 ID 时的数据库中。在您的第二个示例中,位置在其 ID 被访问之前被保存,这就是这样做的原因。

如果您只想稍后保存更改,您将无法依赖位置 ID 来定义关系。

换行...

LocationId = locations[i].Id

...为此...

Location = locations[i]

然后,这些关系将基于不依赖于 LocationID 的对象引用。

【讨论】:

  • 你们谁能看看我的帖子,告诉我如何解决它,我遇到了同样的问题:stackoverflow.com/questions/26783934/…我很感激!
  • 我在部署到测试环境时收到此错误...在开发环境中没有任何想法?
  • @Taran 如果代码相同,并且您在两个环境中使用相同的过程进行测试(我会检查这些点),那么这看起来确实很奇怪。也许您在 dev 中只添加了一个位置(下面是这里的示例)?尝试添加至少两个。
  • 我的问题可能是这个问题的变体。我将子对象添加到父集合中,而没有明确设置子对象的父属性。我希望 EF 能够解决此问题,但在我明确设置子项的父属性之前收到与 OP 相同的错误。希望这对某人有所帮助。
【解决方案2】:

如果这对未来的读者有任何用处,在我的情况下,这个错误是由于我的数据库中的外键配置不正确(以及从数据库生成的模型)。

我有桌子:

Parent (1-1) Child (1-many) Grandchild

并且 Grandchild 表无意中收到了一个外键,直到它的父 (Child) 和它的祖父 (Parent)。从新保存多个父实体时,我收到此错误。修复已纠正外键。

【讨论】:

  • 在我的情况下,我(愚蠢地)将我的主键基表设置为与我的外键基表相同,并且我的主键列与我的外键列相同羞愧地低头 希望这对某人有所帮助..
【解决方案3】:

遇到同样的错误,我高度怀疑实际问题是位置的定义。简而言之,在 EF Code First 中,我打赌它看起来像这样:

public class Location
{
    public int Id { get; set; }
    ...
    public Location ParentLocation { get; set; }
    [ForeignKey("ParentLocation")]
    public int ParentLocationId { get; set; }
}

换句话说,在问题中,ParentLocation/ParentLocationId 是对该表的递归引用。

ParentLocationId 不可为空。这意味着它将以 0 插入,并且 EF 将抱怨插入,而不是当您迁移时 - 即使事实是一旦迁移运行您有一个表 EF 将永远不会让您插入。

使递归引用返回到同一个表的唯一方法是使递归引用可以为空:

public class Location
{
    public int Id { get; set; }
    ...
    public Location ParentLocation { get; set; }
    [ForeignKey("ParentLocation")]
    public int? ParentLocationId { get; set; }
}

注意int 后面的?

【讨论】:

  • 如果您在创建子位置之前对父位置执行 SaveChanges,旧(不可为空)版本会不会工作?
  • 忽略以上,我是个白痴。您将无法创建第一个位置。
  • 基数是问题所在。正确。
【解决方案4】:

对于那些搜索此例外的人:
就我而言,它未能设置所需的导航属性。

public class Question
{
    //...
    public int QuestionGridItemID { get; set; }
    public virtual QuestionGridItem GridItem { get; set; }
    //...
    public int? OtherQuestionID { get; set; }
    public Question OtherQuestion { get; set; }
}

//...

question.OtherQuestion = otherQuestion;
questionGridItem.Questions.Add(question);
dataContext.SaveChanges(); //fails because otherQuestion wasn't added to 
//any grid item's Question collection

【讨论】:

    【解决方案5】:

    我有同样的问题。以下情况为我解决了。 我认为您必须更改您的代码,如下所示:

    var insertedRoute =routeRep.Insert(route);
    .....
    insertedRoute.LocationInRoute = new List<LocationInRoute>();
    for(....){
        var lInRoute = new LocationInRoute(){
        ....
        Route=insertedRoute;
    }
    
    insertedRoute.LocationInRoute.Add(lInRoute );
    }
    

    【讨论】:

      猜你喜欢
      • 2018-02-08
      • 1970-01-01
      • 2012-01-21
      • 1970-01-01
      • 1970-01-01
      • 2013-09-15
      • 2016-06-14
      • 1970-01-01
      • 2013-02-16
      相关资源
      最近更新 更多