programing

엔티티 프레임워크를 사용하여 기본 키 값 업데이트

bestprogram 2023. 5. 27. 12:03

엔티티 프레임워크를 사용하여 기본 키 값 업데이트

엔티티 프레임워크 내에서 복합 기본 키의 한 값을 업데이트하려고 하는데 다음 오류가 발생합니다. "속성 '고객'ID'는 개체의 키 정보의 일부이므로 수정할 수 없습니다."

내 코드는 다음과 같습니다.

Dim customer As Customer = (From c In db.Customer Where c.CustomerID = "xxx" AndAlso c.SiteKey = siteKey).FirstOrDefault
customer.CustomerID = "fasdfasdf"
db.SaveChanges()

너무 간단한 것 같아요.엔티티 프레임워크 내에서 기본 키를 업데이트할 수 없다는 것이 사실입니까?이 주제에 대한 문서를 찾을 수 없습니다.감사합니다!

저는 데이터베이스 분야의 cs 박사 학위를 가지고 있기 때문에, 이 대답은 프로그래머의 관점과는 조금 다를 것입니다.올리버 하나피와 관련하여, 키는 대리 키가 아닌 경우 변경될 수 있으며 때때로 변경됩니다.예: 자연 키 또는 컴포지트 키.예를들면.미국에서는 SSN을 변경할 수 있습니다.그러나 수년간 많은 프로그래머들은 이것을 변경할 수 없는 열쇠로 간주하고 그렇게 사용했습니다.외부 키로 구성된 복합 기본 키를 변경하는 것이 훨씬 일반적입니다.

저는 삼원 관계에 있는 데이터베이스를 다루고 있습니다.구체적으로 세 개의 엔티티(각각의 테이블에서 외부 키가 대체 기본 키임).그러나 세 번째 엔터티를 변경하는 동안 두 엔터티 간의 관계를 유지하려면 교차 테이블(MSDN의 순수 조인 테이블이라고도 함) 기본 키의 일부를 변경해야 합니다.이것은 유효한 설계이며 3항 관계 교차표를 제거하고 고유한 대리 키를 가질 수 있는 두 개의 이항 관계 테이블로 대체해야만 개선할 수 있습니다.EF는 이 벌금을 처리할 것입니다.이러한 설계 변경은 (다중->다중)->다중 또는 부모1-부모2->자녀-손자 모델을 만들 것입니다(만약 명확하지 않다면 아래의 예를 참조하십시오).엔티티 프레임워크는 각 관계가 실제로 일대일 관계이기 때문에 이것과 잘 작동할 것입니다.하지만 DB의 관점에서 보면 미친 디자인입니다.그 이유를 예로 들어 보겠습니다.

강의실, 강의실 및 강사가 강의실에서 서로 연관되어 있다고 간주합니다.클래스는 다음을 포함할 수 있습니다.과정 ID, 강의실ID, 강사외부 키로 ID를 지정하고 세 개의 키를 모두 포함하는 복합 기본 키를 포함합니다.명확하고 간결한 삼원 모델(3차 관계)이지만 이항 관계로 나눌 수 있습니다.이렇게 하면 두 개의 교차로 표를 얻을 수 있습니다.대리 키를 추가하면 다음과 같이 EF가 충족됩니다.

클래스(키클래스 대리, 강사)ID, 과정아이디)

사용 중인 클래스 룸(사용 중인 대리 키 클래스, 대리 키 클래스, 강의실)아이디)

이 설계의 문제는 이전 모델이 피할 수 있는 동일한 과정과 강사를 여러 번 연결할 수 있다는 것입니다.이 문제를 방지하기 위해 두 ID 필드의 고유성에 대한 제약 조건을 데이터베이스에 추가할 수 있습니다. 하지만 처음에는 대리 키만 다루는데 왜 이 작업을 수행하려고 하는 이유는 무엇입니까?하지만 이 해결책은 제가 아는 한 가장 잘 작동할 것입니다.그러나 DB에 요구되는 자연스럽지 않은 고유 제약 조건 때문에 논리 데이터베이스 설계는 아닙니다.

그러나 데이터베이스를 변경하고 싶지 않거나 데이터베이스를 변경할 수 없는 경우 다음과 같은 두 번째 솔루션이 있습니다.교차로/연결 테이블은 두 개 이상의 엔티티를 함께 연결하는 링크입니다.연결이 변경되면 연결을 삭제하고 적절한 외부 키(탐색 속성)가 있는 새 연결을 다시 만듭니다.이것은 여러분이 어떤 관계에서도 자식 개체를 요구할 수 없다는 것을 의미합니다.

우아한 DB 모델을 설계할 수 있는 사람들이 원할 때 교차점/연결 테이블의 키 부분을 변경할 수 있도록 Entity Framework(미래)를 제안합니다!

무료로 제공되는 다른 예:

학생, 과정, 학년 협회를 고려합니다.학생들은 성적을 통해 과정과 연결됩니다.일반적으로 이것은 Grade라고 하는 연관 테이블의 추가 필드를 가진 학생과 과정 간의 많은 연관성입니다(관련 테이블은 grade와 같은 페이로드 데이터를 가지며 교차로 테이블은 페이로드를 가지지 않으며 MSDN에서 한 곳에서 순수 조인 테이블로 참조됨).

학생(학생)ID, ...)

과정(과정 ID, ...)

테이크(학생)ID, 과정ID, 등급)

다른 사용자가 드롭다운에서 데이터 입력 오류를 범하여 잘못된 클래스에 학생을 배치한 경우, 나중에 드롭다운을 다시 선택하고 다른 과정을 선택하여 데이터 입력 오류를 변경할 수 있습니다.백그라운드에서 EF 개체를 Taking 테이블에서 삭제하고 등급이 있는 경우 등급을 잃지 않고 다시 만들어야 합니다.외부 키 과정 변경하기ID가 더 나은 대안인 것 같습니다.이것이 계획적인 것 같으면 당신만의 협회를 생각해 보세요. 하지만 교수로서 저는 당연한 일이었습니다.

결론:일련의 관계를 맺고 있는 경우, 계단식 및/또는 변경 FK를 허용하지 않는 것이 더 나을 수도 있지만, 일반적으로 모범 사례로 권장되지 않더라도 필요한 경우에는 신뢰할 수 있는/논리적인 시나리오가 존재합니다.

이 문제는 탐색 속성 또는 모델의 키 속성을 각각 변경하는 경우에 따라 다음 예외와 함께 나타날 수 있습니다.

참조 무결성 제약 조건 위반이 발생했습니다. 종속 개체가 연결의 기본 개체로 설정되어 있지 않으면 해당 개체가 변경되지 않은 경우 참조 무결성 제약 조건의 일부인 기본 키 속성을 변경할 수 없습니다.주 개체는 추적되어야 하며 삭제 표시되지 않아야 합니다.

속성 'X'는 개체의 키 정보의 일부이므로 수정할 수 없습니다.

엔티티 프레임워크에서는 업데이트할 데이터베이스 행을 알 수 없으므로 엔티티 프레임워크를 통해 기본 키를 업데이트할 수 없습니다.

그러나 실제로 필요한 경우 기본 키를 업데이트하는 저장 프로시저를 작성한 다음 엔티티 프레임워크에서 저장 프로시저를 실행할 수 있습니다.

그럴 수도 없고 그럴 만한 이유도 있습니다.KM 댓글을 참조하십시오.

제가 말씀드릴 수 있는 한 가지는 두 개의 테이블을 갖는 것입니다. 하나는 익명의 데이터를 포함하고 다른 하나는 로그인 후 실제 사용자 데이터를 저장하는 것입니다.

또는 다음과 같은 종류의 테이블 레이아웃을 사용할 수 있습니다(나에 의해 테스트되거나 수행된 적이 없습니다.

---Customers----
AutoNumber PK <- This links to all other tables in your database, and does NOT change.
CustomerID  <- This can change.
CustomerType <- Anonymous or logged in.  

고객이 로그인하면 고객을 변경할 수 있습니다.유형 및 고객당신이 필요한 것에 대한 신분증.

그래서 당신의 질문은 다음과 같습니다.

Dim customer As Customer = (From c In db.Customer _
                            Where c.CustomerID = {Some temp ID} _
                            AndAlso c. CustomerType = "Anonymous").FirstOrDefault
// After user logs in.
customer.CustomerID = {Make a new user ID here}
customer.CustomerType = "LoggedIn" {or what ever}
db.SaveChanges()

자동 번호 기본 는 변경되지 않습니다.이는 고객 테이블과 관계를 맺고 있는 모든 테이블이 여전히 작동하고 기본 키에 대한 계단식 업데이트를 수행할 필요가 없기 때문입니다(연필로 자신의 눈을 찌르는 것과 같습니다).

데이터베이스 컨텍스트의 인스턴스가 한 번에 하나만 있을 수 있다면 pk를 수정하는 것은 문제가 되지 않습니다.그러나 각 컨텍스트 인스턴스는 고유한 캐시를 유지하며 수정할 레코드를 캐싱할 수 있습니다.

데이터베이스와의 EF 상호 작용은 (컨텍스트 캐시에서) pk를 사용하여 쿼리 중인 레코드를 식별합니다.컨텍스트 개체가 키를 지속적으로 업데이트할 수 있는 경우 다른 컨텍스트 개체가 해당 레코드를 식별하는 데 사용하는 정보는 즉시 영구적으로 잘못된 것입니다.

즉, 기본 키를 업데이트하면 잠재적으로 컨텍스트의 다른 모든 인스턴스에서 캐시가 비활성화되어 EF가 기본적으로 손상됩니다.이것이 pk를 업데이트하는 것이 좋지 않은 더 큰 이유 중 하나입니다.

당신은 해야 합니다.delete와 오된실체와.insert수정된 ID로 다시 확인합니다.가장 쉬운 방법은 개체를 JSON 문자열화하여 복제본을 만드는 것입니다.

var cloned_account = DeserializeObject<account>(SerializeObject(existing_account));
cloned_account.user_id = 1;

db.account.Remove(existing_account);
db.account.Add(cloned_account);

기본 키를 업데이트하는 대신 새 기본 키로 다른 행을 삽입하고 이전 행을 삭제하는 것이 좋습니다.그러나 새 기본 키 쌍을 참조하도록 모든 하위 엔티티를 변경해야 합니다.

기본 키를 업데이트할 수는 없지만, 이는 엔티티 프레임워크의 제한이 아니라 데이터베이스 개발의 매우 기본적인 규칙입니다.기본 키는 테이블의 행에 한 번 할당되고 이 행은 고유합니다.
어떤 방식으로든 키를 업데이트할 수 있지만 이는 기본 키의 정의를 명백히 위반합니다.

그러니까, 그냥 하지 마세요, 여러분이 하려고 하는 것을 성취하기 위한 다른 방법들이 있습니다.

언급URL : https://stackoverflow.com/questions/1367751/update-primary-key-value-using-entity-framework