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


132

내가 말할 자유가없는 몇 가지 이유로, 우리는 다음과 같이 Sql Server 2005 데이터베이스에 대한 견해를 정의하고 있습니다.

CREATE VIEW [dbo].[MeterProvingStatisticsPoint]
AS
SELECT
    CAST(0 AS BIGINT) AS 'RowNumber',
    CAST(0 AS BIGINT) AS 'ProverTicketId',
    CAST(0 AS INT) AS 'ReportNumber',
    GETDATE() AS 'CompletedDateTime',
    CAST(1.1 AS float) AS 'MeterFactor',
    CAST(1.1 AS float) AS 'Density',
    CAST(1.1 AS float) AS 'FlowRate',
    CAST(1.1 AS float) AS 'Average',
    CAST(1.1 AS float) AS 'StandardDeviation',
    CAST(1.1 AS float) AS 'MeanPlus2XStandardDeviation',
    CAST(1.1 AS float) AS 'MeanMinus2XStandardDeviation'
WHERE 0 = 1

아이디어는 Entity Framework 가이 쿼리를 기반으로 엔티티를 작성하지만 다음과 같은 오류로 생성합니다.

경고 6002 : 테이블 / 뷰 'Keystone_Local.dbo.MeterProvingStatisticsPoint'에 기본 키가 정의되어 있지 않습니다. 키가 유추되었으며 정의가 읽기 전용 테이블 / 뷰로 작성되었습니다.

그리고 CompletedDateTime 필드가이 엔티티 기본 키가되도록 결정합니다.

우리는 EdmGen을 사용하여 모델을 생성하고 있습니다. 엔터티 프레임 워크에이 뷰의 필드를 기본 키로 포함시키지 않는 방법이 있습니까?

답변:


245

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

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

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

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

예:

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

2
나는 이것이 최선이라고 생각합니다. 결론은 작동합니다.
MvcCmsJon

1
감사합니다! 완벽하게 작동했습니다. @sabanito 나는 그것이 정의를 파싱한다고 생각한다. 그렇기 때문에 IsNull ()의 주요 속성을 구체적으로 래핑해야합니다. null을 반환하지 않고 null을 반환 할 수없는 뷰가 있지만 논리가 작성된 방식으로 인해 EF는 키를 IsNull ()로 줄 바꿈하기 전까지는 그렇지 않은 것으로 판단했습니다.
Rabbi

3
내가 볼 수있는 유일한 문제는보기가 합법적으로 빈 문자열을 반환해야 할 수 있다는 것입니다 ''. 내가 한 것은 단순히 열을 자체 데이터 형식으로 다시 캐스팅하는 것입니다. 예를 들어 AnotherProperty의 데이터 유형이 varchar (50) 인 경우 'CONVERT (VARCHAR (50), AnotherProperty) AS [AnotherProperty]'로 캐스트합니다. 이것은 EF에서 널 (null) 가능성을 숨기고 빈 문자열도 허용했습니다.
Bart

2
예 예를 들면,이 작업은 EF가 같이 PK ( ''()) NEWID, CONVERT (VARCHAR (50)) 기본 키 ISNULL 같이 열을 사용하여 만들
dc2009

2
솔루션에 성가신 메시지가있는 것 외에도이 문제를 해결하지 않으면 어떤 해가 있습니까? 나는 당신의 해결책에 동의하지만 솔직히 나는 이것을해야한다고 생각하지 않습니다-우리 모두 이것이 이것이 버그라는 것에 동의 할 수 있습니까?
dyslexicanaboko

67

디자이너를 사용하여이 문제를 해결할 수있었습니다.

  1. 모델 브라우저를 엽니 다.
  2. 다이어그램에서보기를 찾으십시오.
  3. 기본 키를 마우스 오른쪽 버튼으로 클릭하고 "엔터티 키"가 선택되어 있는지 확인하십시오.
  4. 기본이 아닌 모든 키를 여러 개 선택하십시오. Ctrl 또는 Shift 키를 사용하십시오.
  5. 속성 창에서 (필요한 경우 F4 키를 누름) "엔터티 키"드롭 다운을 False로 변경하십시오.
  6. 변경 사항을 저장하다.
  7. Visual Studio를 닫았다가 다시여십시오. EF 6과 함께 Visual Studio 2013을 사용하고 있으며 경고를 없애기 위해이 작업을 수행해야했습니다.

ISNULL, NULLIF 또는 COALESCE 해결 방법을 사용하기 위해 뷰를 변경할 필요가 없었습니다. 데이터베이스에서 모델을 업데이트하면 경고가 다시 나타나지만 VS를 닫았다가 다시 열면 사라집니다. 디자이너에서 변경 한 내용은 유지되며 새로 고침의 영향을받지 않습니다.


9
확인했습니다. 경고가 사라지도록 VS2013을 다시 시작해야합니다.
Michael Logutov

5
"전원을 껐다 켜 보셨습니까?" ;-) 감사합니다, 매력처럼 작동합니다!
Obl Tobl

4
뷰를 생성 할 때 모델 다이어그램에 포함되지도 않습니다. 그들은 xml 파일에 주석을 달았습니다
ggderas

간단하고 쉬운 솔루션이며 뷰를 조작하는 것만 큼 노키 해킹이 아닌 것처럼 보입니다! 감사합니다.
LuqJensen

2
경고가 사라지려면 확인 된 VS2017을 다시 시작해야합니다.
Marc Levesque 2016 년

46

@Tillito에 동의하지만 대부분의 경우 SQL 최적화 프로그램을 손상시키고 올바른 인덱스를 사용하지 않습니다.

누군가에게는 분명 할 수 있지만 Tillito 솔루션을 사용하여 성능 문제를 해결하는 데 몇 시간을 소비했습니다. 테이블이 있다고 가정 해 봅시다.

 Create table OrderDetail
    (  
       Id int primary key,
       CustomerId int references Customer(Id),
       Amount decimal default(0)
    );
 Create index ix_customer on OrderDetail(CustomerId);

당신의 관점은 다음과 같습니다

 Create view CustomerView
    As
      Select 
          IsNull(CustomerId, -1) as CustomerId, -- forcing EF to use it as key
          Sum(Amount) as Amount
      From OrderDetail
      Group by CustomerId

SQL Optimizer는 인덱스 ix_customer를 사용하지 않고 기본 인덱스에서 테이블 스캔을 수행하지만 다음과 같은 경우에 수행합니다.

Group by CustomerId

너는 사용한다

Group by IsNull(CustomerId, -1)

MS SQL (적어도 2008 년)은 올바른 인덱스를 계획에 포함시킵니다.

만약


2
이것은 OP의 질문에 대한 해결책을 제공하지 않기 때문에 답변 자체가 아닌 Tillito의 답변에 대한 의견이어야합니다.
zimdanen

6
그 사람은 1의 담당자를 가지고 있지만 아직 코멘트를 추가 할 수 없습니다.
jrcs3

@zimdanen이 모든 정보를 주석에 넣을 수있는 방법은 없습니다. 별도의 답변으로 정보를받는 것이 더 합리적입니다.
Contango

2
@Contango :이 답변은 게시 된 지 6 일 후에 편집되었으며 내 의견을 게시했습니다. 개정 이력을 참조하십시오.
zimdanen

9

이 방법은 저에게 효과적입니다. 1 차 키 필드에 ISNULL ()을 사용하고 필드가 1 차 키가 아니어야하지만 널값이 아닌 값을 가져야하는 경우 COALESCE ()를 사용합니다. 이 예에서는 널 입력 불가능 기본 키가있는 ID 필드를 생성합니다. 다른 필드는 키가 아니며 Nullable 속성으로 (없음)을 갖습니다.

SELECT      
ISNULL(P.ID, - 1) AS ID,  
COALESCE (P.PurchaseAgent, U.[User Nickname]) AS PurchaseAgent,  
COALESCE (P.PurchaseAuthority, 0) AS PurchaseAuthority,  
COALESCE (P.AgencyCode, '') AS AgencyCode,  
COALESCE (P.UserID, U.ID) AS UserID,  
COALESCE (P.AssignPOs, 'false') AS AssignPOs,  
COALESCE (P.AuthString, '') AS AuthString,  
COALESCE (P.AssignVendors, 'false') AS AssignVendors 
FROM Users AS U  
INNER JOIN Users AS AU ON U.Login = AU.UserName  
LEFT OUTER JOIN PurchaseAgents AS P ON U.ID = P.UserID

기본 키가없는 경우 ROW_NUMBER를 사용하여 스푸핑하여 코드에서 무시되는 의사 키를 생성 할 수 있습니다. 예를 들면 다음과 같습니다.

SELECT
ROW_NUMBER() OVER(ORDER BY A,B) AS Id,
A, B
FROM SOMETABLE

그래, 나는 속임수를 NEWID() as id썼지 만 같은 생각이다. 예를 들어 읽기 전용보기가있는 경우 합법적 인 사용 사례가 있습니다. 못생긴 EF, 못생긴
ruffin

4

현재 Entity Framework EDM 생성기는보기의 널 입력 불가능 필드에서 복합 키를 작성합니다. 이를 제어하려면 기본 키의 일부로 원하지 않는 경우 열을 널 입력 가능으로 설정하는보기 및 기본 테이블 열을 수정해야합니다. EDM에서 생성 된 키로 인해 데이터 중복 문제가 발생했기 때문에 그 반대도 마찬가지입니다. 따라서 EDM의 복합 키가 해당 열을 포함하도록 nullable 열을 null이 아닌 열로 정의해야했습니다.


우리는 추론 된 PK와 같은 문제를 가지고 있으며, 실체는 중복 된 레코드를 반환하고 완전히 성가신 상태입니다. Context.Entity.ToList()중복 레코드 를 실행 하지만 EF에서 직접 생성 한 SQL 쿼리 (LINQPad로 획득)를 실행하면 레코드 중복이 발생하지 않습니다. PK가 설명 된 논리 (널링 불가능 열)를 사용하여 추론되므로 데이터베이스 레코드를 리턴 된 엔티티 오브젝트 (POCO)에 맵핑하는 데 문제가있는 것 같습니다.
David Oliván Ubieto

3

말이 되네요 그렇다면 열을 정의하는 방식으로 열을 null 또는 null이 아닌 것으로 정의하는 방법이 있습니까?
Sergio Romero

1
죄송합니다. 이미 Entity Framework에 대한 전문 지식 수준을 벗어났습니다. :-)
RBarryYoung 2016 년

1
이 문제가 언제 해결 될지 아는 사람이 있습니까? 기본 키가 아닌 null이 아닌 열이있을 때이 문제를 해결하는 데 어려움이 있습니다.
라이브 사랑

3

난 단지 보여주기 위해했던보기 얻으려면 하나 내가 처음과 사용 NULLIF에 대한 지적이 유형이 널 만들 수있는 두 번째보기를 생성 기본 키 열을. 이것은 EF가 뷰에 단 하나의 기본 키가 있다고 생각하게 만들었습니다.

EF가 기본 키가없는 엔터티를 수락 할 것이라고 믿지 않기 때문에 이것이 도움이되는지 확실하지 않습니다.


3

기본 키가 무엇인지 엉망으로 만들고 싶지 않은 경우 다음을 권장합니다.

  1. ROW_NUMBER당신의 선택에 통합
  2. 기본 키로 설정
  3. 모델에서 다른 모든 열 / 멤버를 기본이 아닌 것으로 설정

1

위에서 언급 한 문제로 인해 테이블 ​​값 함수를 선호합니다.

이것이 있다면 :

CREATE VIEW [dbo].[MyView] AS SELECT A, B FROM dbo.Something

이것을 만드십시오 :

CREATE FUNCTION MyFunction() RETURNS TABLE AS RETURN (SELECT * FROM [dbo].[MyView])

그런 다음 뷰 대신 함수를 가져 오기만하면됩니다.


2
이 접근 방식을 사용하는 엔터티간에 연관성을 어떻게 만들 수 있습니까? 가능합니까?
ggderas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.