这是我的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;
}
我想在方法之外调用一次提交。为什么它在第一个例子中失败了,这个例外意味着什么?
答案 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 );
}