Несколько добавленных объектов могут иметь один и тот же первичный ключ
вот моя модель из 3 объектов: маршрут, местоположение и 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'. Несколько добавленных сущностей могут иметь один и тот же первичный ключ.
при раскалывании фиксация и вставка в methos-это работает:
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 один раз и вне метода. Почему это не удается в первом примере и что означает это исключение?
5 ответов:
ошибка вызвана идентификатором внешнего ключа (в отличие от ссылки), который не может быть разрешен. В вашем случае у вас есть LocationInRole, который ссылается на местоположение с идентификатором 0. Есть несколько мест с этим идентификатором.
места еще не были назначены ID, потому что они еще не были сохранены в базе данных, которая является, когда идентификатор генерируется. Во втором примере местоположения сохраняются до доступа к их идентификаторам, поэтому это завод.
вы не сможете полагаться на идентификаторы местоположения для определения отношений, если вы хотите сохранить изменения только позже.
замените следующую строку...
LocationId = locations[i].Id
...для этого...
Location = locations[i]
отношения будут основаны на ссылках на объекты, которые не зависят от LocationIDs.
в случае, если это имеет какую-либо пользу для будущих читателей, в моем случае эта ошибка была вызвана неверно настроенным внешним ключом в моей базе данных (и модели, созданной из БД).
У меня были таблицы:
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 не является Nullable. Это означает, что он будет вставлен с 0, и EF будет жаловаться на Insert, а не когда вы мигрируете - даже если правда один раз эта миграция выполняется у вас есть таблица EF никогда не позволит вам вставить.
единственный способ сделать рекурсивную ссылку обратно в ту же таблицу работы, чтобы сделать рекурсивную ссылку nullable:
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 ); }