[C#] DefiningQuery가 있고 <UpdateFunction> 요소가 없기 때문에 EntitySet을 업데이트 할 수 없습니다.

.net 3.5에서 Entity Framework 1을 사용하고 있습니다.

나는 이와 같은 간단한 일을하고있다 :

var roomDetails = context.Rooms.ToList();

foreach (var room in roomDetails)
{
   room.LastUpdated = DateTime.Now;
}

시도 할 때이 오류가 발생합니다.

 context.SaveChanges();

오류가 발생합니다.

EntitySet을 업데이트 할 수 없습니다. DefiningQuery가 있고 현재 조작을 지원하기 위해 <ModificationFunctionMapping> 요소에 <UpdateFunction> 요소가 없기 때문에 EntitySet을 업데이트 할 수 없습니다.

컨텍스트에서 많은 업데이트를 수행하고 있으며 문제가 없습니다.이 특정 엔티티를 업데이트하려고 할 때만 발생합니다.

모든 검색에서 동일한 내용이 표시됩니다. 업데이트하려는 엔티티에 기본 키가 선언되어 있지 않습니다. 그러나 아아, 기본 키가 선언되어 있습니다 …



답변

일반적으로 다음과 같은 이유로 발생합니다.

  • 엔티티 세트는 데이터베이스보기에서 맵핑됩니다.
  • 맞춤 데이터베이스 쿼리
  • 데이터베이스 테이블에 기본 키가 없습니다

이렇게 한 후에도 오류가 발생하기 전에 Entity Framework 디자이너에서 업데이트하거나 엔터티를 삭제 한 다음 추가해야 할 수도 있습니다.


답변

테이블에 기본 키를 추가하십시오. 그게 다야. 문제 해결됨.

ALTER TABLE <TABLE_NAME>
ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)


답변

이것은 나를위한 경우입니다. 단순히 제거하면 다른 오류가 발생했습니다. 마지막 게시물을 제외하고이 게시물의 단계를 따랐습니다. 귀하의 편의를 위해 다음과 같이 게시물에서 4 단계를 복사하여 문제를 해결했습니다.

  1. edmx 파일을 마우스 오른쪽 단추로 클릭하고 연결 프로그램, XML 편집기를 선택하십시오.
  2. edmx : StorageModels 요소에서 엔티티를 찾으십시오.
  3. DefiningQuery를 완전히 제거하십시오.
  4. 이름 바꾸기 store:Schema="dbo"Schema="dbo"(그렇지 않으면 코드는 이름을 말하는 오류가 발생합니다 잘못되었습니다)

답변

그냥 어쩌면 당신의주의 엔티티는 기본 키 하지만 데이터베이스에 테이블 이없는 기본 키를 .


답변

업데이트 : 최근에 이것에 대해 몇 가지 공감대를 얻었으므로 사람들이 내가 아래에 제공하는 조언이 최고가 아님을 알릴 것이라고 생각했습니다. 처음에는 오래된 키가없는 데이터베이스에서 Entity Framework를 수행하는 것에 대해 고민하기 시작했기 때문에 BY FAR로 할 수있는 최선의 방법은 코드 우선 역순으로 수행하는 것임을 알게되었습니다. 이 작업을 수행하는 방법에 대한 몇 가지 좋은 기사가 있습니다. 그냥 따르고 키를 추가하려면 데이터 주석을 사용하여 키를 “가짜”로 만드십시오.

예를 들어, 내 테이블을 알고 Orders있지만 기본 키는 없지만 고객 당 하나의 주문 번호 만 보장됩니다. 이것들은 테이블의 처음 두 열이기 때문에 다음과 같이 코드 첫 번째 클래스를 설정했습니다.

    [Key, Column(Order = 0)]
    public Int32? OrderNumber { get; set; }

    [Key, Column(Order = 1)]
    public String Customer { get; set; }

이렇게하면 주문 번호와 고객으로 구성된 클러스터 된 키가 있다고 믿기 위해 기본적으로 EF를 위조합니다. 이를 통해 키가없는 테이블에서 삽입, 업데이트 등을 수행 할 수 있습니다.

리버스 코드 우선 작업에 익숙하지 않은 경우 Entity Framework Code First에 대한 유용한 자습서를 찾아보십시오. 그런 다음 Reverse Code First (기존 데이터베이스에서 Code First)를 수행하십시오. 그런 다음 여기로 돌아와서 나의 주요 조언을 다시보십시오. 🙂

원래 답변 :

첫째 : 다른 사람들이 말했듯이 가장 좋은 방법은 기본 키를 테이블에 추가하는 것입니다. 마침표. 이 작업을 수행 할 수 있으면 더 이상 읽지 마십시오.

그러나 자신을 미워할 수 없거나 미워한다면 기본 키없이 할 수있는 방법이 있습니다.

필자의 경우, 레거시 시스템 (원래 AS400의 플랫 파일은 Access로 포트 된 다음 T-SQL로 포트 된 파일)로 작업하고있었습니다. 그래서 나는 길을 찾아야했다. 이것이 나의 해결책이다. 다음은 Entity Framework 6.0 (이 글을 쓰는 시점에서 NuGet의 최신 버전)을 사용하여 나를 위해 일했습니다.

  1. 솔루션 탐색기에서 .edmx 파일을 마우스 오른쪽 버튼으로 클릭하십시오. “연결 프로그램 …”을 선택한 다음 “XML (텍스트) 편집기”를 선택하십시오. 여기서 자동 생성 된 코드를 직접 편집 할 것입니다.

  2. 다음과 같은 줄을 찾으십시오.
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. store:Name="table_name"끝에서 제거하십시오 .

  4. 변경 store:Schema="whatever"Schema="whatever"

  5. 해당 줄 아래를보고 <DefiningQuery>태그를 찾으십시오 . 그것에 큰 ol ‘select 문이있을 것입니다. 태그와 내용을 제거하십시오.

  6. 이제 라인은 다음과 같아야합니다.
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. 우리는 바꿀 다른 것이 있습니다. 파일을 살펴보고 이것을 찾으십시오.
    <EntityType Name="table_name">

  8. 근처에는 기본 키가 없다는 경고 텍스트가 표시 될 수 있으므로 키가 유추되었으며 정의는 읽기 전용 테이블 / 뷰입니다. 그대로 두거나 삭제할 수 있습니다. 삭제했습니다.

  9. 아래는 <Key>태그입니다. 이것이 Entity Framework가 삽입 / 업데이트 / 삭제를 수행하는 데 사용하는 것입니다. 따라서 귀하가이 권리를 준수하는지 확인하십시오. 해당 태그의 속성은 고유하게 식별 가능한 행을 나타내야합니다. 예를 들어, 내 테이블을 알고 orders있지만 기본 키는 없지만 고객 당 하나의 주문 번호 만 보장됩니다.

그래서 내 모습은 다음과 같습니다.

<EntityType Name="table_name">
              <Key>
                <PropertyRef Name="order_numbers" />
                <PropertyRef Name="customer_name" />
              </Key>

진지하게, 이것을 잘못하지 마십시오. 중복이 없어야하더라도 주문 번호와 고객 이름이 동일한 두 개의 행이 내 시스템에 들어갑니다. 으악! 그것이 열쇠를 사용하지 않아 얻는 것입니다! 따라서 Entity Framework를 사용하여 하나를 삭제합니다. 오늘 중복 주문이 유일한 주문임을 알고 있으므로 다음과 같이하십시오.

var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);

뭔지 맞춰봐? 방금 복제본과 원본을 모두 삭제했습니다! Entity Framework에 order_number / cutomer_name이 기본 키라고 말했기 때문입니다. 따라서 duplicateOrder를 제거하라고 말했을 때 백그라운드에서 수행 한 작업은 다음과 같습니다.

DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)

그리고 그 경고와 함께 … 이제 가야합니다!


답변

데이터 모델이 오래된 경우에도 발생할 수 있습니다.

잘하면 이것은 다른 누군가를 좌절시킬 것입니다 🙂


답변

동일한 오류 메시지가 표시되었지만 시나리오에서 PJT (Pure Join Table)를 사용하여 다 대다 관계에서 파생 된 엔티티를 업데이트하려고했습니다.

다른 게시물을 읽었을 때 조인 테이블에 추가 PK 필드를 추가하여 문제를 해결할 수 있다고 생각했습니다. 그러나 조인 테이블에 PK 열을 추가하면 더 이상 PJT가 아니므로 더 이상 PJT가 아닙니다. 엔티티 간의 자동 관계 맵핑과 같은 엔티티 프레임 워크의 장점.

그래서 내 경우의 해결책은 DB의 조인 테이블을 변경하여 외래 ID 열의 BOTH를 포함하는 PK를 만드는 것입니다.