Aquí está mi modelo de 3 entidades: Ruta, Ubicación y LocationInRoute.
el siguiente método falla y obtiene una excepción cuando lo confirma:
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;
}
Al hacer:
InsertRouteIfNotExists(companyId, locations);
UnitOfWork.Commit();
Tengo:
No se puede determinar el final principal de la relación 'SimTaskModel.FK_T_STF_SUB_LOCATION_IN_ROUTE_T_STF_LOCATION_location_id'. Varias entidades agregadas pueden tener la misma clave principal.
Al dividir la confirmación e insertarla en los métodos, funciona:
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;
}
Me gustaría llamar a commit una vez y fuera del método. ¿Por qué falla en el primer ejemplo y qué significa esta excepción?
c#
.net
entity-framework
Naor
fuente
fuente
Respuestas:
El error es causado por un ID de clave externa (a diferencia de una referencia) que no se puede resolver. En su caso, tiene LocationInRole que hace referencia a una ubicación con un ID de 0. Hay varias ubicaciones con este ID.
A las ubicaciones aún no se les ha asignado una identificación porque aún no se han guardado en la base de datos que es cuando se genera la identificación. En su segundo ejemplo, las ubicaciones se guardan antes de que se acceda a sus ID, por lo que esto funciona.
No podrá confiar en los ID de ubicación para definir las relaciones si desea Guardar cambios solo más adelante.
Intercambia la siguiente línea ...
...para esto...
Las relaciones se basarán en referencias de objetos que no dependen de los LocationID.
fuente
En caso de que esto sea de alguna utilidad para futuros lectores, en mi caso, este error se debió a una clave externa configurada incorrectamente en mi base de datos (y el modelo generado desde la base de datos).
Tenía mesas:
Parent (1-1) Child (1-many) Grandchild
y la tabla de nietos había recibido inadvertidamente una clave externa para su padre (hijo) y su abuelo (padre). Al guardar varias entidades principales de nuevas, recibí este error. La solución ha sido corregir la clave externa.
fuente
Habiendo encontrado el mismo error, sospecho que el problema real era la definición de Ubicación. En pocas palabras, en EF Code First, apuesto a que se ve así:
public class Location { public int Id { get; set; } ... public Location ParentLocation { get; set; } [ForeignKey("ParentLocation")] public int ParentLocationId { get; set; } }
En otras palabras, en la pregunta, ParentLocation / ParentLocationId son una referencia recursiva a esta tabla.
ParentLocationId no admite nulos. Eso significa que se insertará con un 0, y EF se quejará en Insert, en lugar de cuando migre, aunque la verdad es que una vez que se ejecuta la migración, tiene una tabla en la que EF nunca le permitirá insertar.
La única forma de hacer una referencia recursiva a la misma tabla funciona es hacer que la referencia recursiva sea anulable:
public class Location { public int Id { get; set; } ... public Location ParentLocation { get; set; } [ForeignKey("ParentLocation")] public int? ParentLocationId { get; set; } }
Tenga en cuenta el
?
después delint
.fuente
Para aquellos que buscan esta excepción:
en mi caso, no se pudo establecer una propiedad de navegación requerida.
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
fuente
Tuve el mismo problema. con el siguiente escenario resuelto para mí. Creo que debe cambiar su código como se muestra a continuación:
var insertedRoute =routeRep.Insert(route); ..... insertedRoute.LocationInRoute = new List<LocationInRoute>(); for(....){ var lInRoute = new LocationInRoute(){ .... Route=insertedRoute; } insertedRoute.LocationInRoute.Add(lInRoute ); }
fuente