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

C# 多个添加的实体可能具有相同的主键,c#,.net,entity-framework,C#,.net,Entity Framework,这是我的3个实体模型:路线、位置和地点路线。 以下方法失败,并在提交时获取异常: public static Route InsertRouteIfNotExists(Guid companyId, IListLocation> locations) { //Loop on locations and insert it without commit InsertLocations(companyId, routesOrL

这是我的3个实体模型:路线、位置和地点路线。

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

 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;
        }
我得到:

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

将提交和插入拆分到Methods中时,它会起作用:

  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;
            }
公共静态路由InsertRouteIfNotExists(Guid companyId,IListLocation>locations)
{
//在位置上循环并插入它而不提交
插入位置(公司ID、路线或位置);
UnitOfWork.Commit();
RouteRepository routeRep=新的RouteRepository();
Route Route=routeRep.Findulote(公司ID,地点);
如果(路由==null)
{
路由=新路由()
{
CompanyId=CompanyId,
IsDeleted=false
};
路线插入(路线);
LocationInRouteRepository locInRouteRep=新位置InRouteRepository();
对于(int i=0;i

我想在方法之外调用commit一次。在第一个示例中失败的原因以及此异常意味着什么?

该错误是由无法解决的外键ID(与引用相反)引起的。在本例中,您有一个LocationInRole,它引用ID为0的位置。有多个位置具有此ID

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

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

交换以下行

LocationId = locations[i].Id
…为了这个

Location = locations[i]

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

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

我有桌子:

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

而且孙子表无意中收到了一个外键,该外键指向它的父(子)和祖父母(父)。从new中保存多个父实体时,我收到此错误。修复方法是更正外键。

遇到相同的错误后,我高度怀疑实际问题是位置的定义。简单地说,在EF代码中,首先我打赌它是这样的:

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

后面的

在我的例子中,它未能设置所需的导航属性

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

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

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

insertedRoute.LocationInRoute.Add(lInRoute );
}
var insertedourite=routeRep.Insert(路由);
.....
InsertedRoote.LocationInRoute=新列表();
对于(……){
var lInRoute=新位置inroute(){
....
路线=插入式;
}
InsertedRoote.LocationInRoute.Add(lInRoute);
}

@Ladislav Mrnka:我没有老板,这是我的项目。我真的不知道你从哪里得到这样的印象,我马上问你。你不是唯一一个整天使用电脑的人。免费咨询?有人给任何人保证他的答案吗?我相信这是一个可以在这里提问的论坛,这就是我正在做的。我有很多问题,我相信多亏了这个论坛和像你这样的人,我才有了一个长距离的学习。参与是一个选择。@Ladislav:我只看到一个问得很好的问题,OP的配置文件也没有显示任何过度。您在整个操作范围内使用相同的ObjectContext,还是每个新存储库都有自己的ObjectContext?@Akash Kava:我使用的是相同的ObjectContext。您可以看看我的帖子并告诉我如何解决它吗?我得到了同样的问题:我很感激!当我部署到test env(测试环境)时,我遇到了这个错误…不在dev Environment中有任何想法吗?@Taran如果代码相同,并且您在两个环境中使用相同的过程进行测试(我会检查这些点),那么这看起来确实很奇怪。也许您只是在dev中添加了一个位置(下面是示例)?尝试添加至少两个。我的问题可能是这一个的变体。我将子对象添加到父对象集合中,而没有显式设置子对象的父属性。我希望EF能够解决这个问题,但在我显式设置子对象的父属性之前,收到了与OP相同的错误。希望这对其他人有所帮助。在我的例子中,我(愚蠢地)将主键基表设置为与外键基表和主键列t相同
var insertedRoute =routeRep.Insert(route);
.....
insertedRoute.LocationInRoute = new List<LocationInRoute>();
for(....){
    var lInRoute = new LocationInRoute(){
    ....
    Route=insertedRoute;
}

insertedRoute.LocationInRoute.Add(lInRoute );
}