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

时间:2011-05-18 07:06:28

标签: c# .net entity-framework

这是我的3个实体模型:Route,Location和LocationInRoute model

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

 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;
            }

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

5 个答案:

答案 0 :(得分:132)

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

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

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

交换以下行......

LocationId = locations[i].Id

...为此...

Location = locations[i]

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

答案 1 :(得分:4)

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

我有桌子:

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

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

答案 2 :(得分:1)

遇到同样的错误我非常怀疑实际问题是Location的定义。简单地说,在EF Code First中,我打赌它看起来像这样:

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

换句话说,在Question中,ParentLocation / ParentLocationId是返回此表的递归引用。

ParentLocationId不是Nullable。这意味着它将插入一个0,EF会在Insert上投诉,而不是在你迁移时 - 即使事实是一次迁移运行你有一个表,EF永远不会让你插入。< / p>

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

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

请注意?之后的int

答案 3 :(得分: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

答案 4 :(得分:0)

我有同样的问题。以下场景为我解决了。 我认为你必须改变你的代码,如下所示:

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

insertedRoute.LocationInRoute.Add(lInRoute );
}