Oto mój model 3 jednostek: Route, Location i LocationInRoute.
poniższa metoda zawodzi i otrzyma wyjątek po jej zatwierdzeniu:
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;
}
Robiąc:
InsertRouteIfNotExists(companyId, locations);
UnitOfWork.Commit();
Mam:
Nie można określić głównego końca relacji „SimTaskModel.FK_T_STF_SUB_LOCATION_IN_ROUTE_T_STF_LOCATION_location_id”. Wiele dodanych jednostek może mieć ten sam klucz podstawowy.
Podczas dzielenia zatwierdzenia i wstawiania do methos - działa:
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;
}
Chciałbym wywołać commit raz i poza tą metodą. Dlaczego zawodzi w pierwszym przykładzie i co oznacza ten wyjątek?
c#
.net
entity-framework
Naor
źródło
źródło
Odpowiedzi:
Błąd jest spowodowany identyfikatorem klucza obcego (w przeciwieństwie do odwołania), którego nie można rozwiązać. W Twoim przypadku masz LocationInRole, która odwołuje się do lokalizacji o identyfikatorze 0. Istnieje wiele lokalizacji o tym identyfikatorze.
Lokacjom nie przypisano jeszcze identyfikatora, ponieważ nie zostały one jeszcze zapisane w bazie danych, w której jest generowany identyfikator. W drugim przykładzie lokalizacje są zapisywane przed uzyskaniem dostępu do ich identyfikatorów, dlatego to działa.
Nie będziesz mógł polegać na identyfikatorach lokalizacji w celu zdefiniowania relacji, jeśli chcesz zapisać zmiany dopiero później.
Zamień następującą linię ...
...dla tego...
Relacje będą wówczas oparte na odwołaniach do obiektów, które nie są zależne od identyfikatorów lokalizacji.
źródło
W przypadku, gdy jest to przydatne dla przyszłych czytelników, w moim przypadku ten błąd był spowodowany nieprawidłowo skonfigurowanym kluczem obcym w mojej bazie danych (i modelu wygenerowanym z bazy danych).
Miałem tabele:
Parent (1-1) Child (1-many) Grandchild
a tabela wnuków przypadkowo otrzymała klucz obcy do swojego rodzica (dziecka) i dziadka (rodzica). Podczas zapisywania wielu podmiotów nadrzędnych z nowego, otrzymałem ten błąd. Poprawka polegała na poprawieniu klucza obcego.
źródło
Po napotkaniu tego samego błędu podejrzewam, że rzeczywistym problemem była definicja lokalizacji. Mówiąc prościej, w EF Code First założę się, że wyglądało to tak:
public class Location { public int Id { get; set; } ... public Location ParentLocation { get; set; } [ForeignKey("ParentLocation")] public int ParentLocationId { get; set; } }
Innymi słowy, w pytaniu ParentLocation / ParentLocationId są rekursywnymi odwołaniami do tej tabeli.
ParentLocationId nie dopuszcza wartości Nullable. Oznacza to, że zostanie wstawiony z 0, a EF będzie narzekać na wstawianie, a nie podczas migracji - nawet jeśli prawda jest taka, że po uruchomieniu migracji masz tabelę EF, która nigdy nie pozwoli ci wstawić.
Jedynym sposobem, aby odwołanie rekurencyjne z powrotem do tej samej tabeli działało, jest ustawienie wartości nullable referencji rekurencyjnej:
public class Location { public int Id { get; set; } ... public Location ParentLocation { get; set; } [ForeignKey("ParentLocation")] public int? ParentLocationId { get; set; } }
Zwróć uwagę na
?
point
.źródło
Dla tych, którzy szukają tego wyjątku: w
moim przypadku nie udało się ustawić wymaganej właściwości nawigacji.
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
źródło
miałem ten sam problem. z poniższym scenariuszem rozwiązanym dla mnie. myślę, że musisz zmienić swój kod, taki jak poniżej:
var insertedRoute =routeRep.Insert(route); ..... insertedRoute.LocationInRoute = new List<LocationInRoute>(); for(....){ var lInRoute = new LocationInRoute(){ .... Route=insertedRoute; } insertedRoute.LocationInRoute.Add(lInRoute ); }
źródło