27

アプリケーションを生のADO.NETと埋め込みSQLからエンティティに変換するプロジェクトを開始しました。アプリケーションで使用されているビューの1つで問題が発生しました。ビューには、行を一意に識別する主キーと列(または列の組み合わせ)がありません。ビューが作成される選択は次のとおりです。

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 

insuredidはaip.slbtransinsuredテーブルのpk、rsnはaip.slbtransinsurerおよびaip.slblinecodesのpkです。

一意の識別子なしでエンティティモデルにビューを追加することは可能ですか?または、ビューに一意の行識別子を追加する簡単な方法はありますか?ビューはから読み取られるだけで、書き込まれることはありません。

4

6 に答える 6

38

一意の識別子なしでエンティティモデルにビューを追加することは可能ですか?

主キーがない場合は、いいえ。その結果、この種のエラーが発生します。

モデルの生成中に1つ以上の検証エラーが検出されました。

System.Data.Edm.EdmEntityType ::EntityType'SalesOnEachCountry'にはキーが定義されていません。このEntityTypeのキーを定義します。System.Data.Edm.EdmEntitySet:EntityType:EntitySet SalesOnEachCountryListは、キーが定義されていないタイプSalesOnEachCountryに基づいています。

一意の識別子がない場合は、はい、望ましくない出力がありますが。同じ識別子を持つレコードは同じオブジェクトを参照します。これはIDマップパターンと呼ばれます

たとえば、ビューで次の2つの行が生成される場合でも次のようになります。

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クエリエディタで上記の2つの行を生成する場合でも、EntityFrameworkは次の誤った出力を生成します。

Country     Year TotalSales
Philippines 2010 20.000000
Philippines 2010 20.000000

Entity Frameworkは、2番目の行が最初の行と同じオブジェクトであると見なします。

一意性を保証するには、各行を一意にする列を特定する必要があります。上記の例では、主キーが一意になるように年を含める必要があります。すなわち

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; }
}

主キーを上記の属性と同様にすることで、EntityFrameworkは各ビューの行を独自のオブジェクトに正しくマップできます。したがって、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]RNプロパティに属性を割り当てますclass RowNumberedView

于 2012-07-07T02:31:00.797 に答える
21

Michael Buenからの回答を拡張すると、ISNULL()を使用してビューに行番号を追加すると、エンティティフレームワークがビューをプルして、必要なEntitySetデータを自動的に作成できることがわかりました。

create view RowNumberedView as

select 
    ISNULL(ROW_NUMBER() OVER (ORDER BY <column>), 0) AS RN
    , *
from your_existing_view
于 2016-02-19T22:33:43.137 に答える
3

最近仕事で、私はこれと同じ問題に遭遇しました。私の調査によると、PKなしでEF6CodeFirstにビューを添付する方法についての回答は見つかりませんでした。ほとんどが移行を伴うようで、かなり混乱していました。私は、DBが最初に作業をより適切にサポートしていると信じていSQL VIEWSます。

window functionEF6を幸せに保つために行識別子をPKとして使用するという考えで、(RowNumber)を導入してみました。しかし、これは私のクエリを全体的に高価にしたので、私はこのアイデアを捨てなければなりませんでした。

最終的に、データセットを注意深く分析して、複合キーを導入できるかどうかを確認する必要がありました。これは、ビジネスアプリケーションが確実に機能するために必要なすべてのシナリオをカバーするものです。CodeFirstIsNull(ColumnName,0)の流暢なメソッドを確実に満たすためにも使用することを忘れないでください。.IsRequired()

すなわち

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

これが誰かに役立つことを願っています-私にとっての答えは、ビューが非正規化するデータセットを分析し、複合キーを探すことでした。

MarcCalsが提案したもう1つのクールなアイデア。

于 2018-04-27T15:20:58.277 に答える
1

ASP.NETでMVCを使用してEntityFrameworkを使用している場合

前に述べたように、自動インクリメントまたはROW_NUMBERを持つ列を使用してビューを作成します。その列があり、その名前が。であるとしrowNumberます。

MVCアプリケーションのディレクトリにあるコンテキストファイル(yourDatabaseNameContext)ファイルに移動し、代わりにビューの定義を見つけますModels

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

次のように変更します。

 modelBuilder.Entity<yourView>(entity =>
            {
                entity.HasKey(e => e.rowNumber);
于 2020-05-11T16:12:04.693 に答える
0

一意の識別子なしでエンティティモデルにビューを追加することは可能ですか?

主キーを作成する単一の列または列のセットがないビューを持つことができます。したがって、あなたは偽の関係になってしまいます。データウェアハウステーブルは、その形式に従う場合があります。つまり、パフォーマンス上の理由またはレポート上の理由のいずれかのために、正規化に従わない場合があります。

次に、2番目のポイントに移ります。

または、ビューに一意の行識別子を追加する簡単な方法はありますか?

slbtransinsuredからすべての列を選択し、各レコードを一意に識別する1つの列を見つけることができるかどうかを確認することをお勧めします。データは、ルックアップのように、選択する必要のあるslblinecodesのコードタイプがあるはずだと私には思えます。

キックの場合は、これを実行してみて、何が得られるか教えてください。

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;
于 2012-07-06T23:00:56.380 に答える
-1

ビューを使用するときは、AsNoTracking()の使用を検討してください。これにより、EFトラッキングのキーフィールドの使用が無効になります。次に、null以外のフィールドをEFキーとして手動で定義できます(繰り返しても)。

ほとんどの行カウンターでは、述語(where句)を使用してクエリを実行する場合でも、エンジンがビューのドメイン全体をスキャンして適切なカウンター値を生成する必要があるため、追加の行カウンターフィールドを作成しないことをお勧めします。

リンクをご覧ください。

于 2015-04-02T23:40:24.780 に答える