多个添加的实体可能具有相同的主键


80

这是我的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;
            }

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


9
@Ladislav Mrnka:我没有老板,这是我的项目。我真的不知道您对我有什么印象,我马上就提出要求。您不是唯一一整天使用计算机的人。免费咨询?有人给任何人保证他的答案吗?我相信这是一个可以在此处提出问题的论坛,这就是我正在做的事情。我有很多问题,而且我相信我可以通过这个论坛和像你这样的人进行很多学习。参加是一个选择。
瑙尔

1
@Ladislav:我只看到一个问得很好的问题,并且OP的个人资料也没有在顶部显示任何内容。
汉克·霍尔特曼

您是在整个操作范围内使用相同的ObjectContext还是每个新存储库都有其自己的ObjectContext?
阿卡什·卡瓦

@Akash Kava:我正在使用相同的ObjectContext。
瑙尔,

Answers:


144

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

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

如果仅以后要保存更改,则将不能依靠位置ID来定义关系。

交换以下行...

LocationId = locations[i].Id

...为了这...

Location = locations[i]

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


你们两个可以看看我的帖子并告诉我如何解决它吗,我遇到了同样的问题:stackoverflow.com/questions/26783934/…非常感谢!
duxfox-- 2014年

我在部署测试环境时收到此错误...在dev environemnet中没有任何想法吗?
塔兰

@Taran如果代码相同,并且您在两个环境中使用相同的过程进行测试(我会检查这些要点),那么这确实很奇怪。也许您只在dev中添加了一个位置(下面是此示例)?尝试添加至少两个。
Scott Munro

我的问题可能是这一个的变化。我将子对象添加到父对象的集合中,而没有在子对象上显式设置parent属性。我希望EF能够解决此问题,但是在我明确设置子项的父级属性之前,会收到与OP相同的错误。希望这对某人有帮助。
Eric H

4

如果这对将来的读者有用,那么在我的情况下,此错误是由于数据库(以及从数据库生成的模型)中的外键配置不正确引起的。

我有桌子:

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

并且孙子表在不经意间收到了一个外键,直到它的父母(孩子)和祖父母(父母)为止。从新保存多个父实体时,我收到此错误。已修复了更正外键的问题。


在我来说,我有(愚蠢)设置我的主键基表一样我的外键基本表和我的主键列相同,我的外键列弓头耻辱希望这可以帮助别人..
戴夫

2

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

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

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

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

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

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

请注意?后的int


如果在创建子位置之前在父位置执行SaveChanges,那么旧版本(不可为空)将无法工作吗?
安德烈·科普斯(AndréKops),

1
忽略上面,我是个白痴。您将无法创建第一个位置。
安德烈·科普斯(AndréKops),

基数是问题。正确。
aclalex

0

对于那些搜索此异常的用户:
就我而言,它无法设置必需的导航属性。

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

0

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

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

insertedRoute.LocationInRoute.Add(lInRoute );
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.