Entity Framework : 기본 키가없는 테이블


165

기존 DB를 사용하여 새 앱을 만들고 싶습니다. EF4.0

일부 테이블에는 기본 키가 정의되어 있지 않으므로 새 엔터티 데이터 모델을 만들 때 다음 메시지가 나타납니다.

The table/view TABLE_NAME does not have a primary key defined 
and no valid primary key could be inferred. This table/view has 
been excluded. To use the entity, you will need to review your schema, 
add the correct keys, and uncomment it.

그것들을 사용하고 데이터를 수정하고 싶다면 반드시 그 테이블에 PK를 추가해야합니까? 아니면 해결 방법이 있습니까?


21
Joe Celko를 인용하면 : 기본 키가 없으면 테이블이 아닙니다 . 왜 지구상에서 누구나 기본 키없이 "일반적인"테이블을 만들겠습니까? 그 PK를 추가하십시오! 나중에 필요할 것입니다 ....
marc_s

4
보기 만해도이 사례는 stackoverflow.com/a/10302066/413032
Davut Gürbüz

50
모든 테이블에 기본 키가 필요한 것은 아닙니다. 종종 유용하지는 않지만 유효합니다. 혼란스러운 EF는 많은 이유가 아니라 좋은 이유 중 하나입니다. ;-).
Suncat2000

25
회사에서 DB 구조를 수정할 수없고 테이블 구조를 변경하지 않는 누군가가 만든 것으로 가정하면이 시나리오가 가능합니다.
Tito

4
바로 우리가있는 곳입니다. 기본 키가없는 타사 Oracle 데이터베이스를 사용해야합니다.
David Brower

답변:


59

오류는 정확히 말한 것을 의미합니다.

이 문제를 해결할 수 있다고하더라도 나를 믿지 마십시오. 도입 될 수있는 혼란스러운 버그의 수는 놀랍고 무섭습니다. 성능이 튜브를 떨어 뜨릴 수 있다는 사실은 말할 것도 없습니다.

이 문제를 해결하지 마십시오. 데이터 모델을 수정하십시오.

편집 : 나는 많은 사람들 이이 질문을 내리는 것을 보았습니다. 괜찮습니다.하지만 OP 는 뷰가 아닌 기본 키가없는 테이블 매핑에 대해 물었습니다 . 대답은 여전히 ​​같습니다. EF가 테이블에 PK를 보유해야 할 필요성을 해결하는 것은 관리 효율성, 데이터 무결성 및 성능 측면에서 나쁜 생각입니다.

일부는 타사 응용 프로그램에 매핑하기 때문에 기본 데이터 모델을 수정하는 기능이 없다고 언급했습니다. 모델이 아래에서 바뀔 수 있기 때문에 좋은 생각이 아닙니다. 아마도이 경우에는 OP에 요청한 것이 아닌 뷰에 매핑하고 싶을 것입니다.


44
공통 시나리오에서는 동의하지만 LOG 테이블과 같은 희귀 시나리오에서는 최대한 빨리 레코드를 삽입하면됩니다. 고유성을 확인하고 색인을 생성 할 때 PK가 문제가 될 수 있습니다. 또한 PK가 IDENT이므로 생성 된 값을 EF로 반환하는 것도 또 다른 문제입니다. GUID를 대신 사용하십니까? 생성 시간과 인덱싱 / 정렬은 또 다른 문제입니다! ... SO PK가없는 중요한 OLTP 시나리오 (로깅과 같은)에서 중요한 점이 있습니다.
Mahmoud Moravej 2012 년

5
@MahmoudMoravej : 우선, 클러스터링 인덱스와 기본 키의 아이디어를 섞지 마십시오. 그들은 같은 것이 아닙니다. IDENTITY 열에 클러스터 된 인덱스가있는 테이블에서 성능이 뛰어난 삽입을 가질 수 있습니다. 인덱스 유지 관리에 문제가 발생하면 테이블을 올바르게 분할해야합니다. 클러스터형 인덱스가없는 테이블을 남겨두면 삭제 후 공간을 확보하기 위해 효과적으로 조각 모음을 수행 할 수 없습니다. 인덱스가없는 경우 로깅 테이블을 쿼리하려고하는 가난한 사람을 불쌍히 여깁니다.
Dave Markle

149
"데이터 모델 수정"은 실제 답변이 아닙니다. 때때로 우리는 우리가 만들지 않았고 바꿀 수없는 이상적이지 않은 상황에서 살아야합니다. @Colin이 말했듯이 OP가 요구 한 것을 정확하게 수행 할 수있는 방법이 있습니다.
TheSmurf

13
EF를 만족시키기 위해 코드를 변경하는 것은 그 자체로 해결 방법입니다. 모든 테이블에 기본 키가 필요한 것은 아니며 강제로 수행되어야하는 것은 아닙니다. 예를 들어 주제가 있고 키워드가 0 개 또는 여러 개입니다. 키워드 표는 상위 주제 ID와 해당 키워드를 가질 수 있습니다. EF가 저를 강요하기 때문에 DB를 리모델링해야한다고 말하십시오.
Mr. 12'12'12

14
질문에 대답하지 않기 때문에 다운 투표되어야합니다. 종종 변경할 수없는 타사 데이터베이스를 사용해야합니다.
Kurren

104

나는 이것이 Tillito에 의해 해결되었다고 생각합니다.

엔터티 프레임 워크 및 SQL Server보기

아래에 그의 항목을 인용하겠습니다.

우리는 같은 문제가 있었고 이것이 해결책입니다.

엔티티 프레임 워크가 열을 기본 키로 사용하도록하려면 ISNULL을 사용하십시오.

엔티티 프레임 워크가 열을 기본 키로 사용하지 않도록하려면 NULLIF를 사용하십시오.

이것을 적용하는 쉬운 방법은 뷰의 select 문을 다른 select로 감싸는 것입니다.

예:

SELECT
  ISNULL(MyPrimaryID,-999) MyPrimaryID,
  NULLIF(AnotherProperty,'') AnotherProperty
  FROM ( ... ) AS temp

생성 26 apr. 102012-04-26 17:00 : Tillito


6
+1 이것은 정답입니다. 완벽한 세상에서 모든 레거시 데이터베이스를 참조 무결성을 갖도록 수정하고 수정하는 것이 좋지만 실제로는 항상 가능하지는 않습니다.
Dylan Hayes

9
나는 이것을 권장하지 않습니다. 특히 ISNULL 부분입니다. EF가 두 PK를 동일하게 감지하면 고유 레코드를 렌더링하지 않고 공유 객체를 반환 할 수 있습니다. 이것은 전에 나에게 일어났다.
Todd

@Todd-MyPrimaryID가 NOT NULL 열인 경우 어떻게 될 수 있습니까?
JoeCool

@JoeCool은 NULL이 아니라고해서 이것이 고유하다는 의미는 아닙니다. 나는 "이 솔루션은 작동합니다 ..."를 올렸습니다. 어떤 컨텍스트에서 사용 되든 독창성을 보장 할 수 있기 때문입니다. 지금 생각하고 있지만 레코드가 삭제되면 다음 레코드의 "PK"가 효과적으로 변경됩니다.
Todd

1
-1, ID 시드가없는 테이블에 매핑하는 방법을 처리하기 위해 Entity Framework / C # 코드를 구성하는 방법에 대한 답변이 없기 때문입니다. 어떤 이유로 써드 파티 소프트웨어가 이런 식으로 작성되었습니다.
Andrew Gray

27

그것들을 사용하고 데이터를 수정하고 싶다면 반드시 그 테이블에 PK를 추가해야합니까? 아니면 해결 방법이 있습니까?

이 질문에 도달하고 Entity Framework Core를 사용하는 사용자는 더 이상 해당 테이블에 PK를 추가하거나 해결 방법을 수행 할 필요가 없습니다. EF Core 2.1부터 새로운 기능인 쿼리 유형이 있습니다.

다음에 쿼리 유형을 사용해야합니다.

  • 임시 FromSql () 쿼리의 반환 유형으로 사용됩니다.
  • 데이터베이스 뷰에 매핑
  • 기본 키가 정의되지 않은 테이블에 매핑
  • 모델에 정의 된 쿼리에 매핑

그래서 DbContext 단지 유형의 다음과 같은 속성을 추가 DbQuery<T>하는 대신 DbSet<T>아래처럼. 테이블 이름을 가정하면 MyTable:

public DbQuery<MyTable> MyTables { get; set; }

1
EF Core를 사용하는 경우 최상의 답변입니다!
Jay

17

Entity Framework Fluent API를 사용하여 복합 키를 수행 할 수도 있습니다.

public class MyModelConfiguration : EntityTypeConfiguration<MyModel>
{
     public MyModelConfiguration()
     {
        ToTable("MY_MODEL_TABLE");
        HasKey(x => new { x.SourceId, x.StartDate, x.EndDate, x.GmsDate });
        ...
     }
}

이런 종류의 '수동 매핑'의 경우, 사용자 정의 키를 지정하는 것이 효과적이라는 것을 알았습니다. 또한 복합 키의 이점이없는 경우 (이 답변에 표시된 것처럼) 자연 스럽거나 복합적이지 않지만 신뢰할 수있는 특수 키에 대해 modelBuilder.Entity<T>()체인 콜에 태그를 지정할 .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)수 있습니다 독특하게 (보통 어쨌든)
Andrew Gray

5

필자의 경우 엔터티를 기본 키가없는 View에 매핑해야했습니다. 또한이보기를 수정할 수 없었습니다. 다행히이 뷰에는 고유 한 문자열 인 열이있었습니다. 내 솔루션은이 열을 기본 키로 표시하는 것이 었습니다.

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[StringLength(255)]
public string UserSID { get; set; }

속이는 EF. 완벽하게 작동했지만 아무도 눈치 채지 못했습니다 ... :)


UserID코드 우선 접근 방식을 사용하면 열 이 생성 됩니다 ..!
Deepak Sharma

1
EF를 속이지 않았습니다. 방금 Itentity기능을 끄라고 명령했습니다 . 기본적으로, 내가 옳다면 여전히 UserIDPK로 열 을 만들지 만 UserID기본적으로 새 레코드를 만들 때 자동으로 시간을 늘리지 않습니다 . 또한에 고유 한 값을 유지해야합니다 UserID.
Celdor

1
@Celdor UserSID는 문자열이며 "자동으로 증가"되지 않습니다. 정수 ID 열인 경우 데이터베이스는 Entity Framework가 아니라 삽입시이를 증가시킵니다.
reggaeguitar

4

EF는 데이터베이스에 기본 키가 필요하지 않습니다. 그렇다면 엔터티를 뷰에 바인딩 할 수 없습니다.

SSDL (및 CSDL)을 수정하여 고유 필드를 기본 키로 지정할 수 있습니다. 당신이 독특한 분야가 없다면, 나는 당신이 호스에 있다고 생각합니다. 그러나 실제로는 고유 한 필드 (및 PK)가 있어야합니다. 그렇지 않으면 나중에 문제가 발생할 수 있습니다.

에릭


이것은 ISNULL 핵을 피합니다. 그러나 상황에 따라 다른 답변이 필요할 수 있습니다. 예를 들어 EF의 PK에서 일부 데이터 유형이 지원되지 않는 느낌이 있습니다.
Todd

3

쓸모없는 신원 키를 갖는 것은 때때로 무의미합니다. ID를 사용하지 않으면 왜 추가해야합니까? 그러나 엔터티는 그렇게 용서하지 않으므로 ID 필드를 추가하는 것이 가장 좋습니다. 사용되지 않은 경우에도 누락 된 ID 키에 대한 엔티티의 지속적인 오류를 처리하는 것보다 낫습니다.


3

이 솔루션 작동

PK가 없어도 수동으로 매핑 할 필요는 없습니다. 열 중 하나가 색인이고 색인 열이 널 입력 가능하지 않다는 것을 EF에 알려 주면됩니다.

이렇게하려면 다음과 같이 isNull 함수를 사용하여 뷰에 행 번호를 추가 할 수 있습니다

select 
    ISNULL(ROW_NUMBER() OVER (ORDER BY xxx), - 9999) AS id
from a

ISNULL(id, number) 이 열이 기본 키가 될 수 있음을 EF에 알려주기 때문에 여기서 핵심 사항


2
그래도 ISNULL 부분은 제안하지 않습니다. EF가 두 PK를 동일하게 감지하면 고유 레코드를 렌더링하지 않고 대신 공유 객체를 반환 할 수 있습니다. 이것은 전에 나에게 일어났다.
Todd

1
Isull을 사용해야합니다. 그렇지 않으면 EF가 Null을 허용하지 않는다고 생각하지 않습니다.
Archlight

2

PK가 없으면 위의 답변이 정확합니다.

그러나 DB에 색인이 지정되어 있지 않고 DB에 색인으로 지정되지 않은 경우 DB를 변경할 수 없습니다 (예, Dilbert의 세계에서 일하고 있음) 수동으로 필드를 키로 매핑 할 수 있습니다.


2

이것은 @Erick T의 답변에 추가 된 것입니다. 고유 한 값을 가진 단일 열이 없으면 해결 방법은 다음과 같이 복합 키를 사용하는 것입니다.

[Key]
[Column("LAST_NAME", Order = 1)]
public string LastName { get; set; }

[Key]
[Column("FIRST_NAME", Order = 2)]
public string FirstName { get; set; }

다시 말하지만 이것은 단지 해결 방법입니다. 실제 솔루션은 데이터 모델을 수정하는 것입니다.


2

이 답변에 늦을 수도 있지만 ...

테이블에 기본 키가 없으면 EF가 제대로 작동하기 위해 분석해야 할 시나리오가 거의 없습니다. EF는 기본 키가있는 테이블 / 클래스와 함께 작동합니다. 그것이 추적하는 방법입니다 ...

예를 들어, 테이블 1. 레코드는 고유합니다. 고유성은 단일 외래 키 열에 의해 만들어집니다. 2. 레코드는 고유합니다. 고유성은 여러 열의 조합에 의해 만들어집니다. 3. 레코드는 고유하지 않습니다 (대부분의 경우 *).

시나리오 # 1 및 # 2의 경우 DbContext 모듈 OnModelCreating 메소드에 다음 행을 추가 할 수 있습니다. modelBuilder.Entity (). HasKey (x => new {x.column_a, x.column_b}); // 레코드를 고유하게 만드는 데 필요한 열 수

시나리오 # 3의 경우 테이블을 연구 한 후에도 여전히 위의 솔루션 (# 1 + # 2)을 사용할 수 있습니다 (* 어쨌든 모든 레코드를 고유하게 만드는 이유). 모든 레코드를 고유하게 만들기 위해 모든 열을 포함해야하는 경우 기본 키 열을 테이블에 추가 할 수 있습니다. 이 테이블이 타사 공급 업체의 경우이 테이블을 복제 스크립트를 통해 임의로 추가 된 기본 키 열을 사용하여이 테이블을 로컬 데이터베이스 (야간 또는 필요한 시간)에 복제하십시오.


1
  1. 테이블 구조를 변경하고 기본 열을 추가하십시오. 모델 업데이트
  2. XML 편집기에서 .EDMX 파일을 수정하고이 특정 테이블의 태그 아래에 새 열을 추가하십시오 (작동하지 않음)
  3. 종료 테이블에 새 기본 열을 만드는 대신 기존 열을 모두 포함하여 복합 키를 만듭니다 ( WORKED ).

엔터티 프레임 워크 : 엔터티 모델에 기본 키가없는 DataTable 추가


EF 4.0으로 복합 키 접근을 시도했지만 작동하지 않았습니다.
Ralph Willgoss

이 접근법은 나를 위해 완벽하게 작동했습니다. 레거시 시스템 "때때로"작업하는 데 어려움을
겪을

1

@CodeNotFound 의 답변으로 업데이트하십시오 .

EF Core 3.0 DbQuery<T>에서는 더 이상 사용되지 않으므로 대신 동일한 작업을 수행하는 Keyless 엔티티 유형 을 사용해야합니다 . 이들은 ModelBuilder HasNoKey()메소드 로 구성됩니다 . DbContext 클래스에서 다음을 수행하십시오.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<YourEntityType>(eb =>
        {
            eb.HasNoKey();
        });

}

그러나 특히 제한 사항이 있습니다.

  • DbContext의 변경 사항을 추적하지 않으므로 데이터베이스에서 삽입, 업데이트 또는 삭제되지 않습니다.
  • 다음과 같은 탐색 매핑 기능의 하위 집합 만 지원합니다.
    • 그들은 결코 관계의 주요한 끝으로 행동 할 수 없습니다.
    • 소유 한 엔티티에 대한 탐색이 없을 수 있습니다.
    • 정규 엔티티를 가리키는 참조 탐색 특성 만 포함 할 수 있습니다.
    • 엔티티에는 키가없는 엔티티 유형에 대한 탐색 특성이 포함될 수 없습니다.

이것은

그것들을 사용하고 데이터를 수정하고 싶다면 반드시 그 테이블에 PK를 추가해야합니까? 아니면 해결 방법이 있습니까?

이 방법으로 데이터를 수정할 수는 없지만 읽을 수는 있습니다. 데이터를 수정하기 위해 다른 방법 (예 : ADO.NET, Dapper)을 사용하여 구상 할 수 있습니다. 이는 읽기 작업이 거의 필요하지 않고 대부분의 경우 EF Core를 계속 사용하려는 경우의 솔루션 일 수 있습니다.

또한 힙 (키리스) 테이블로 작업 해야하는 경우 / EF를 버리고 다른 방법으로 데이터베이스와 대화하십시오.


0

실제적인 관점에서 볼 때, 모든 테이블 (예 :웨어 하우스 테이블과 같은 비정규 화 된 테이블)에도 기본 키가 있어야합니다. 또는 실패하면 적어도 nullable이 아닌 고유 인덱스가 있어야합니다.

고유 한 키가 없으면 테이블에 중복 레코드가 나타날 수 있으며 이는 ORM 계층과 데이터의 기본 이해에 모두 문제가됩니다. 중복 레코드가있는 테이블은 아마도 잘못된 디자인의 증상 일 것입니다.

최소한 테이블에는 최소한 ID 열이 있어야합니다. 자동 생성 ID 열을 추가하려면 SQL Server에서 약 2 분, Oracle에서 5 분이 걸립니다. 그 여분의 노력으로 많은 문제를 피할 수 있습니다.


내 응용 프로그램이 Oracle과 함께 데이터웨어 하우스 설정에 있으며 5 분 동안 인덱스를 추가하도록 안내했습니다. 실제로 5 분 밖에 걸리지 않습니다 (또는 ETL 을 조회 하거나 수정 해야하는 경우 약간 더 소요됨 ).
Trent

0

우리는이 문제도 발생했으며 null이있는 열이 있었지만 중요한 것은 null이없는 종속 열이 있고이 두 열의 조합이 고유하다는 것입니다.

Pratap Reddy의 답변을 인용하면 우리에게 잘 작동했습니다.


0

문제가 해결되어 매우 기쁩니다.

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

그리고 이것을하십시오 : 그 줄 아래를보고 태그를 찾으십시오. 그것에 큰 ol 'select 문이있을 것입니다. 태그와 내용을 제거하십시오.

DB TI를 변경하지 않고도 PK가없는 테이블에 삽입 할 수 있음

모두 감사하고 Pharylon에게 감사합니다



-8

테이블에는 null을 허용하지 않는 하나의 열이 필요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.