Вот моя модель из трех объектов: 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;
}
Я хотел бы вызвать фиксацию один раз и вне метода. Почему это не удается в первом примере и что означает это исключение?
c#
.net
entity-framework
Наор
источник
источник
Ответы:
Ошибка вызвана идентификатором внешнего ключа (в отличие от ссылки), который не может быть разрешен. В вашем случае у вас есть LocationInRole, который ссылается на Location с идентификатором 0. Существует несколько местоположений с этим идентификатором.
Местоположениям еще не был присвоен идентификатор, потому что они еще не были сохранены в базе данных, когда создается идентификатор. Во втором примере местоположения сохраняются до доступа к их идентификаторам, поэтому это работает.
Вы не сможете полагаться на идентификаторы местоположения для определения отношений, если хотите сохранить изменения только позже.
Поменяйте местами следующую строку ...
...за это...
Тогда отношения будут основаны на ссылках на объекты, которые не зависят от LocationID.
источник
Если это будет полезно для будущих читателей, в моем случае эта ошибка возникла из-за неправильно настроенного внешнего ключа в моей базе данных (и модели, созданной из БД).
У меня были таблицы:
Parent (1-1) Child (1-many) Grandchild
и таблица Grandchild случайно получила внешний ключ до своего родителя (Child) и его прародителя (Parent). При сохранении нескольких родительских сущностей из новых я получил эту ошибку. Исправление заключалось в исправлении внешнего ключа.
источник
Столкнувшись с той же ошибкой, я очень подозреваю, что на самом деле проблема заключалась в определении местоположения. Проще говоря, в EF Code First, я уверен, это выглядело так:
public class Location { public int Id { get; set; } ... public Location ParentLocation { get; set; } [ForeignKey("ParentLocation")] public int ParentLocationId { get; set; } }
Другими словами, в вопросе ParentLocation / ParentLocationId - это рекурсивная ссылка на эту таблицу.
ParentLocationId не допускает значения Null. Это означает, что он будет вставлен с 0, и EF будет жаловаться на Insert, а не при миграции - хотя правда в том, что после запуска миграции у вас есть таблица, в которую 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 ); }
источник