Кілька доданих об’єктів можуть мати однаковий первинний ключ


81

Ось моя модель 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'. Кілька доданих об’єктів можуть мати однаковий первинний ключ.

Розбиваючи коміт і вставляючи в метод - це працює:

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

Я хотів би викликати коміт один раз і поза методом. Чому це не вдається в першому прикладі і що означає цей виняток?


9
@Ladislav Mrnka: У мене немає боса, і це мій проект. Я справді не знаю, звідки у вас складається враження, що я відразу запитую про SO. Ви не єдиний, хто користується комп’ютером цілий день. Консультація безкоштовно? хтось дає комусь гарантію за його відповіді? Я вважаю, що це форум, де тут можна задавати питання, і я цим займаюся. У мене є багато питань, і я вважаю, що завдяки цьому форуму та таким людям, як ти, я навчусь на великих дистанціях. Участь - вибір.
Наор,

1
@Ladislav: Я бачу лише досить добре поставлене запитання, і в профілі ОП також не вказано нічого зверху.
Хенк Холтерман

Чи використовуєте ви один і той же ObjectContext протягом усього обсягу операцій, або кожне нове сховище матиме власний ObjectContext?
Акаш Кава,

@Akash Kava: Я використовую той самий ObjectContext.
Наор,

Відповіді:


144

Помилка викликана ідентифікатором зовнішнього ключа (на відміну від посилання), який неможливо вирішити. У вашому випадку у вас є LocationInRole, яка посилається на розташування з ідентифікатором 0. З цим ідентифікатором є кілька розташувань.

Місцеположенням ще не присвоєно ідентифікатор, оскільки вони ще не збережені в базі даних, саме тоді генерується ідентифікатор. У вашому другому прикладі місцеположення зберігаються до доступу до їх ідентифікаторів, саме тому це працює.

Ви не зможете покладатися на ідентифікатори місцезнаходження для визначення відносин, якщо ви захочете зберегти зміни лише пізніше.

Поміняйте місцями наступний рядок ...

LocationId = locations[i].Id

...для цього...

Location = locations[i]

Потім зв’язки будуть базуватися на посиланнях на об’єкти, які не залежать від ідентифікаторів Location.


може хтось із вас поглянути на мій пост і сказати мені, як я можу це виправити, я отримую ту саму проблему: stackoverflow.com/questions/26783934/… Я ціную це!
duxfox

Я отримую цю помилку, коли я розгортаю тестувати env ... немає в dev environemnet жодних ідей?
Таран

@Taran Якщо код ідентичний, і ви використовуєте один і той же процес для тестування в обох середовищах (я б перевірив ці пункти), це видається дивним. Можливо, ви додаєте лише одне розташування (далі за прикладом тут) у dev? Спробуйте додати принаймні два.
Скотт Манро,

Моя проблема може бути різновидом цього. Я додавав дочірні об'єкти до батьківської колекції без явного встановлення батьківського властивості для дітей. Я очікував, що EF вирішить цю проблему, але отримав ту ж помилку, що і OP, поки явно не встановив батьківську властивість для дочірньої організації. Сподіваюся, це комусь допомагає.
Eric H

4

Якщо це буде корисно для майбутніх читачів, у моєму випадку ця помилка була пов’язана з неправильно налаштованим зовнішнім ключем у моїй базі даних (і моделлю, створеною з БД).

У мене були таблиці:

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

і стіл Онука ненароком отримав зовнішній ключ аж до батьківського (Дитина) та дідуся (Батька). Після збереження кількох батьківських сутностей від нових, я отримав цю помилку. Виправлено те, що було виправлено зовнішній ключ.


У моєму випадку я (по-дурному) встановив свою базову таблицю первинного ключа так само, як і базову таблицю зовнішнього ключа, і мою колонку первинного ключа так само, як моя колонка зовнішнього ключа, соромно схиляючи голову. Сподіваюся, це комусь допомагає ..
Дейв,

3

Натрапивши на ту саму помилку, я дуже підозрюю, що фактичною проблемою було визначення Місцезнаходження. Простіше кажучи, у 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 .


Чи не спрацює стара (не нульова) версія, якщо зробити SaveChanges у батьківському розташуванні перед створенням дочірнього розташування?
Андре Копс,

1
Ігнорувати вище, я ідіот. Ви не зможете створити перше місце.
Андре Копс,

Проблема полягала в потужності. Правильно.
aclalex

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

0

у мене була така сама проблема. з наведеним нижче сценарієм, вирішеним для мене. я думаю, ви повинні змінити свій код, як показано нижче:

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

insertedRoute.LocationInRoute.Add(lInRoute );
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.