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


81

다음은 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;
            }

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


9
@Ladislav Mrnka : 저는 상사가없고 이것은 제 프로젝트입니다. 내가 즉시 물어 보는 인상을 어디에서 얻었는지 정말 모르겠습니다. 하루 종일 컴퓨터를 사용하는 사람은 당신 만이 아닙니다. 무료 상담? 누군가가 그의 답변에 대해 보증을 제공합니까? 나는 이것이 여기에서 질문을 할 수있는 포럼이고 이것이 내가하는 일이라고 믿는다. 질문이 많고이 포럼과 여러분과 같은 분들 덕분에 먼 거리에서 배울 수 있다고 생각합니다. 참여는 선택입니다.
Naor

1
@Ladislav : 합리적으로 잘 묻는 질문 만 보였고 OP의 프로필은 상단에 아무것도 표시하지 않습니다.
Henk Holterman

작업 범위 전체에서 동일한 ObjectContext를 사용하고 있습니까? 아니면 각각의 새 저장소에 자체 ObjectContext가 있습니까?
Akash Kava

@Akash Kava : 동일한 ObjectContext를 사용하고 있습니다.
Naor

답변:


144

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

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

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

다음 줄을 바꿉니다 ...

LocationId = locations[i].Id

...이를 위해 ...

Location = locations[i]

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


둘 중 한 사람이 내 게시물을보고 어떻게 고칠 수 있는지 알려주세요. 동일한 문제가 발생합니다. stackoverflow.com/questions/26783934/… 감사합니다!
duxfox-- 2014

환경을 테스트하기 위해 배포 할 때이 오류가 발생합니다 ... 개발 환경에서 아이디어가 없습니까?
Taran

@Taran 코드가 동일하고 동일한 프로세스를 사용하여 두 환경에서 테스트하는 경우 (이 점을 확인합니다) 이상하게 보입니다. 아마도 당신은 dev에 하나의 위치 만 추가하고 있는가? 두 개 이상 추가해보세요.
Scott Munro

내 문제는 이것의 변형 일 수 있습니다. 자식에 대한 부모 속성을 명시 적으로 설정하지 않고 부모의 컬렉션에 자식 개체를 추가했습니다. EF가이 문제를 해결할 것으로 예상했지만 자식에 부모 속성을 명시 적으로 설정할 때까지 OP와 동일한 오류가 발생했습니다. 이것이 누군가를 돕기를 바랍니다.
Eric H

4

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

나는 테이블이 있었다 :

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

Grandchild 테이블은 부모 (Child)와 조부모 (Parent)까지의 외래 키를 실수로 수신했습니다. 새 항목에서 여러 상위 항목을 저장할 때이 오류가 발생했습니다. 외래 키를 수정하는 문제가 수정되었습니다.


내 경우에는 내가 (바보가) 내 외부 키 자료 표 내 기본 키 열 내 외래 키 열 같은 같은 내 기본 키 자료 표를 설정했다 활 부끄러움에 머리 희망이 도움이 사람 ..
데이브

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는 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.


하위 위치를 만들기 전에 상위 위치에서 SaveChanges를 수행하면 이전 (nullable이 아닌) 버전이 작동하지 않습니까?
André Kops

1
위는 무시하세요. 저는 바보입니다. 첫 번째 위치를 만들 수 없습니다.
André Kops

카디널리티가 문제였습니다. 옳은.
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 );
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.