bestsource

엔티티에 기본 키가 없는 보기 사용

bestsource 2023. 7. 3. 23:01
반응형

엔티티에 기본 키가 없는 보기 사용

저는 방금 원시 ADO.NET 및 임베디드 SQL에서 Entity로 애플리케이션을 변환하는 프로젝트를 시작했습니다.응용 프로그램에서 사용하는 보기 중 하나에 문제가 발생했습니다.보기에는 기본 키와 행을 고유하게 식별하는 열(또는 열 조합)이 없습니다.다음은 보기가 생성되는 선택 항목입니다.

SELECT
    filingmonth,
    CEIL(filingmonth / 3),
    licnum,
    filingyear,
    DECODE(GROUPING(insurername), '1', '- All Insured -', insurername),
    insurername,
    policylinecode,
    linedescription,
    SUM(NVL(grosspremium, 0)),
    SUM(DECODE(taxexempt, 1, grosspremium, 0)),
    TRUNC(
      CASE
        WHEN
          (
            b.rsn IS NOT NULL
            OR A.zeroreport = 1
          )
          AND b.datereceived IS NULL
            THEN A.datereceived
        ELSE b.datereceived
      END),
    SUM(aip.iscompanyadmitted(b.naiccocode, b.naicalienid)),
    A.insuredid
  FROM
    aip.slbtransinsured A
  LEFT OUTER JOIN aip.slbtransinsurer b
  ON
    A.insuredid = b.insuredid
  LEFT OUTER JOIN aip.slblinecodes C
  ON
    b.policylinecode = C.linecode
  WHERE
    A.submitted = 1
  AND A.entryincomplete = 0
  GROUP BY
    licnum,
    filingmonth,
    filingyear,
    TRUNC(
      CASE
        WHEN
          (
            b.rsn IS NOT NULL
            OR A.zeroreport = 1
          )
          AND b.datereceived IS NULL
            THEN A.datereceived
        ELSE b.datereceived
      END),
    ROLLUP(insurername, aip.iscompanyadmitted(b.naiccocode, b.naicalienid),
    policylinecode, linedescription), A.insuredid;

다음은 완전히 중복된 일부 행(3행 및 4행)이 있음을 보여주는 몇 가지 샘플 데이터는 다음과 같습니다.

FILINGMONTH CEIL(FILINGMONTH/3) LICNUM FILINGYEAR DECODE(GROUPING(INSURERNAME),'1','-ALLINSURED-',INSURERNAME)                                         INSURERNAME                                                                                          POLICYLINECODE LINEDESCRIPTION                                                                                                                                                                                          SUM(NVL(GROSSPREMIUM,0)) SUM(DECODE(TAXEXEMPT,1,GROSSPREMIUM,0)) TRUNC(CASEWHEN(B.RSNISNOTNULLORA.ZEROREPORT=1)ANDB.DATERECEIVEDISNULLTHENA.DATERECEIVEDELSEB.DATERECEIVEDEND) SUM(AIP.ISCOMPANYADMITTED(B.NAICCOCODE,B.NAICALIENID)) INSUREDID

      6                   2   8150       2007 SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            17             OTHER LIABILITY                                                                                                                                                                                                            721.25                                       0 18-JUL-07                                                                                                                                                          0        81 
      6                   2   8150       2007 SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            17                                                                                                                                                                                                                                        721.25                                       0 18-JUL-07                                                                                                                                                          0        81 
      6                   2   8150       2007 SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                                                                                                                                                                                                                                                                      721.25                                       0 18-JUL-07                                                                                                                                                          0        81 
      6                   2   8150       2007 SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                                                                                                                                                                                                                                                                      721.25                                       0 18-JUL-07                                                                                                                                                          0        81 

idiredid는 aip.slb transinsured 테이블의 pk이고, rsn은 aip.slb transinsurer 및 aip.slbline 코드의 pk입니다.

고유 식별자 없이 도면요소 모델에 뷰를 추가할 수 있습니까?아니면 보기에 고유한 행 식별자를 쉽게 추가할 수 있는 방법이 있습니까?보기는 읽기만 하고 쓰기는 하지 않습니다.

고유 식별자 없이 도면요소 모델에 뷰를 추가할 수 있습니까?

기본 키가 없으면 아니요.그러면 다음과 같은 오류가 발생합니다.

모델을 생성하는 동안 하나 이상의 유효성 검사 오류가 감지되었습니다.

시스템. 데이터.Edm.EdmEntity유형: 엔티티'각 국가별 영업' 유형에 정의된 키가 없습니다.이 엔터티 유형에 대한 키를 정의합니다.시스템.데이터. 에드먼.에드먼티집합: 엔티티유형: EntitySetSalesOn각 국가 목록은 키가 정의되지 않은 각 국가의 유형 SalesOn각 국가를 기준으로 합니다.

고유 식별자가 없는 경우, 예, 바람직하지 않은 출력을 가지고 있습니다.동일한 식별자를 가진 레코드는 동일한 개체를 참조합니다. 이를 ID패턴이라고 합니다.

보기가 다음 두 행을 생성하는 경우에도 예제:

Country     Year TotalSales
Philippines 2010 20.000000
Philippines 2011 40.000000

기본 키를 국가 필드에만 매핑하는 경우(예:

public class SalesOnEachCountry
{        
    [Key]
    public int CountryId { get; set; }
    public string CountryName { get; set; }        
    public int OrYear { get; set; }
    public long SalesCount { get; set; }
    public decimal TotalSales { get; set; }
}

보기에서 Oracle 쿼리 편집기에서 위의 두 행을 생성하더라도 Entity Framework는 다음과 같은 잘못된 출력을 생성합니다.

Country     Year TotalSales
Philippines 2010 20.000000
Philippines 2010 20.000000

Entity Framework는 두 번째 행이 첫 번째 행과 동일한 개체라고 간주합니다.

고유성을 보장하려면 각 행을 고유하게 만드는 열을 식별해야 합니다.위의 예에서는 기본 키가 고유하도록 Year를 포함해야 합니다.

public class SalesOnEachCountry
{        
    [Key, Column(Order=0)] public int CountryId { get; set; }
    public string CountryName { get; set; }
    [Key, Column(Order=1)] public int OrYear { get; set; }

    public long SalesCount { get; set; }      
    public decimal TotalSales { get; set; }
}

기본 키를 위의 속성과 유사하게 만들면 Entity Framework는 각 뷰의 행을 고유한 개체에 올바르게 매핑할 수 있습니다.따라서 이제 Entity Framework는 보기와 동일한 행을 표시할 수 있습니다.

Country     Year TotalSales
Philippines 2010 20.000000
Philippines 2011 40.000000

자세한 내용은 http://www.ienablemuch.com/2011/06/mapping-class-to-database-view-with.html 를 참조하십시오.


행을 고유하게 만들 열이 없는 뷰의 경우, Entity Framework가 뷰의 각 행을 자신의 객체에 매핑할 수 있도록 보장하는 가장 쉬운 방법은 뷰의 기본 키에 대해 별도의 열을 만드는 것입니다. 예를 들어, 각 행에 행 번호 열을 만드는 것이 좋습니다.

create view RowNumberedView as

select 
    row_number() over(order by <columns of your view sorting>) as RN
    , *
from your_existing_view

그런 다음 할당합니다.[Key]class RowNumberedView

Michael Buen의 답변 확장: ISNULL()을 사용하여 뷰에 행 번호를 추가하면 엔티티 프레임워크가 뷰를 가져와서 필요한 EntitySet 데이터를 자동으로 생성할 수 있다는 것을 발견했습니다.

create view RowNumberedView as

select 
    ISNULL(ROW_NUMBER() OVER (ORDER BY <column>), 0) AS RN
    , *
from your_existing_view

저는 최근에 직장에서 같은 문제에 부딪혔습니다.제가 조사한 결과, PK 없이 EF6 CodeFirst에 뷰를 첨부하는 방법에 대한 답을 찾을 수 없었습니다.대부분은 이주와 관련된 것으로 보이며 상당히 혼란스러웠습니다.더 잘 합니다.SQL VIEWS.

저는 소개하려고 노력했습니다.window function는 EF6를 행 (으)로 표시되는 PK는 EF6입니다.하지만 이것은 제 질문을 전반적으로 더 비싸게 만들었기 때문에 저는 이 아이디어를 포기해야만 했습니다.

결국, 비즈니스 애플리케이션이 작동하는 데 필요한 모든 시나리오를 다루는 복합 키를 도입할 수 있는지 알아보기 위해 데이터 세트를 신중하게 분석해야 했습니다.사해야함을 사용하는 것을 하세요.IsNull(ColumnName,0)당신이 만족할 수 있도록 보장하기에는 너무..IsRequired()코드퍼스트 유창한 방법으로.

HasKey(x => new { x.KfiId, x.ApplicationNumber, x.CustomerId });

저는 이것이 누군가에게 도움이 되기를 바랍니다 - 저의 대답은 보기가 정규화되지 않는 데이터 세트를 분석하고 복합 키를 찾는 것이었습니다.

마크 칼스가 제안한 또 다른 멋진 아이디어를 시도해 볼 수 있습니다.

ASP.NET에서 MVC와 함께 Entity Framework를 사용하는 경우

앞에서 말한 것처럼 자동 증분 또는 ROW_NUMBER가 있는 열로 뷰를 생성합니다.만약 당신이 그 칼럼을 가지고 있고 그것의 이름은.rowNumber.

go file (콘텍스트 파일로 이동)yourDatabaseNameContext) 에 Models 프로그램의 MVC 응용 .

modelBuilder.Entity<yourView>(entity =>
    {
        entity.HasNoKey();

다음으로 변경:

 modelBuilder.Entity<yourView>(entity =>
            {
                entity.HasKey(e => e.rowNumber);

고유 식별자 없이 도면요소 모델에 뷰를 추가할 수 있습니까?

기본 키를 생성하는 열 또는 열 집합이 하나도 없는 보기를 가질 수 있으므로, 가상 관계가 발생할 수 있습니다.데이터 웨어하우스 테이블이 해당 양식을 따르는 경우도 있습니다.즉, 성능이나 보고의 이유로 정규화가 지켜지지 않는 경우가 있습니다.

이제 두 번째 요점을 말씀드리겠습니다.

아니면 보기에 고유한 행 식별자를 쉽게 추가할 수 있는 방법이 있습니까?

제가 제안하는 것은 slb transinsured에서 모든 열을 선택하고 각 레코드를 고유하게 식별하는 하나의 열을 찾을 수 있는지 확인하는 것입니다.제가 보기에 데이터는 slbline 코드에 당신이 선택해야 하는 코드 유형이 있어야 합니다. 마치 조회와 같습니다.

재미로, 이것을 실행해 보고 무엇을 얻을 수 있는지 말해 보십시오.

SELECT filingmonth,
       CEIL (filingmonth / 3),
       licnum,
       filingyear,
       DECODE (GROUPING (insurername), '1', '- All Insured -', insurername),
       insurername,
       policylinecode,
       linedescription,
       SUM (NVL (grosspremium, 0)),
       SUM (DECODE (taxexempt, 1, grosspremium, 0)),
       TRUNC (
           CASE
               WHEN (b.rsn IS NOT NULL OR a.zeroreport = 1)
                    AND b.datereceived IS NULL
               THEN
                   a.datereceived
               ELSE
                   b.datereceived
           END),
       SUM (aip.iscompanyadmitted (b.naiccocode, b.naicalienid)),
       a.insuredid
  FROM aip.slbtransinsured a
       LEFT OUTER JOIN aip.slbtransinsurer b
           ON a.insuredid = b.insuredid
       LEFT OUTER JOIN aip.slblinecodes c
           ON b.policylinecode = c.linecode
 WHERE a.submitted = 1 AND a.entryincomplete = 0
GROUP BY filingmonth,
         licnum,
         filingyear,
         DECODE (GROUPING (insurername), '1', '- All Insured -', insurername),
         insurername,
         policylinecode,
         linedescription,
         TRUNC (
             CASE
                 WHEN (b.rsn IS NOT NULL OR a.zeroreport = 1)
                      AND b.datereceived IS NULL
                 THEN
                     a.datereceived
                 ELSE
                     b.datereceived
             END),
         a.insuredid;

둘다요.NEWID()그리고.ROW_NUMBER() OVER(...)는 다른 답변에 언급된 대로 고유한 값을 생성하지만 보기 결과에 null로 표시됩니다(값이 null이 아닐 것임을 알고 있음에도 불구하고).이렇게 하면 엔티티 프레임워크에서 키로 선택할 수 없습니다.

수정 사항은 다음과 같이 'ISNULL()'로 묶는 것입니다.

CREATE VIEW MyView
AS
SELECT
    ISNULL(NEWID(), 0x0) as RowId,
    ...
FROM ...

또는

-- *** See performance note below ***
CREATE VIEW MyView
AS
SELECT
    ISNULL(ROW_NUMBER() OVER(ORDER BY (SELECT NULL)), 0) as RowNum,
    ...
FROM ...

그 결과RowId그리고.RowNum이제 열이 뷰 결과에서 분할할 수 없는 유형으로 보고됩니다.할당된 값은 반복할 수 없으며 읽기 전용 사용 사례에만 사용할 수 있습니다.

중요 참고:ROW_NUMBER()바람직하지 않은 성능 문제가 발생할 수 있습니다.결과를 계산하기 위해 SQL Server는 참조 쿼리에 의해 정의될 수 있는 필터를 적용하기 전에 행 번호 값을 검색하여 전체 뷰 행 집합에 할당하는 것으로 나타납니다.예를 들어, 쿼리SELECT * FROM MyView V WHERE V.ActivityDate >= @StartDate AND V.ActivityDate < @EndDate날짜 범위 필터가 적용되기 전에 항상 데이터를 검색하고 행 번호를 할당할 수 있습니다.이는 다음과 같은 경우에 문제가 되지 않습니다.NEWID()사용됩니다.

다양한 양식을 보여주는 이 db<>fidle을 참조하십시오.

보기를 사용할 때 AsNoTracking()을 사용하는 것이 좋습니다.그러면 EF 추적을 위한 키 필드의 사용이 비활성화됩니다.그런 다음 Null이 아닌 필드를 EF 키로 수동으로 정의할 수 있습니다(반복하더라도).

대부분의 행 카운터는 결국 엔진이 뷰의 전체 도메인을 스캔하여 적절한 카운터 값을 생성하도록 요구하기 때문에 추가 행 카운터 필드를 만들지 않는 것이 좋습니다(where 절).

링크를 참조하십시오.

언급URL : https://stackoverflow.com/questions/11370245/using-a-view-with-no-primary-key-with-entity

반응형