[c#] 추가 된 여러 항목이 동일한 기본 키를 가질 수 있습니다.

다음은 Route, Location 및 LocationInRoute의 3 개 엔티티 모델입니다.
모델

다음 메서드가 실패하고 커밋 할 때 예외가 발생합니다.

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

한 번 메서드 외부에서 커밋을 호출하고 싶습니다. 첫 번째 예에서 실패하는 이유와이 예외는 무엇을 의미합니까?



답변

오류는 해결할 수없는 외래 키 ID (참조와 반대)로 인해 발생합니다. 귀하의 경우 ID가 0 인 위치를 참조하는 LocationInRole이 있습니다.이 ID를 가진 위치가 여러 개 있습니다.

위치는 ID가 생성 될 때 데이터베이스에 아직 저장되지 않았기 때문에 아직 ID가 할당되지 않았습니다. 두 번째 예에서는 ID에 액세스하기 전에 위치가 저장되므로 이것이 작동합니다.

나중에 변경 사항을 저장하려는 경우 위치 ID를 사용하여 관계를 정의 할 수 없습니다.

다음 줄을 바꿉니다 …

LocationId = locations[i].Id

…이를 위해 …

Location = locations[i]

그러면 관계는 LocationID에 종속되지 않는 개체 참조를 기반으로합니다.


답변

이것이 미래의 독자들에게 유용 할 경우, 제 경우에는이 오류가 제 데이터베이스 (및 DB에서 생성 된 모델)에 잘못 구성된 외래 키로 인한 것입니다.

나는 테이블이 있었다 :

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는 Nullable이 아닙니다. 즉, 0으로 삽입되고 EF는 마이그레이션 할 때가 아니라 삽입에 대해 불평 할 것입니다. 사실 마이그레이션이 실행되면 테이블 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 );
}


답변