質問

説明する自由がないいくつかの理由により、次のように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を使用してモデルを生成しています。エンティティフレームワークにこのビューのフィールドを主キーとして含めない方法はありますか?

役に立ちましたか?

解決

同じ問題があり、これが解決策です:

エンティティフレームワークで列を主キーとして使用するには、ISNULLを使用します。

エンティティフレームワークで主キーとして列を使用しないようにするには、NULLIFを使用します。

これを適用する簡単な方法は、ビューのselectステートメントを別のselectでラップすることです。

例:

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

他のヒント

デザイナーを使用してこれを解決できました。

  1. モデルブラウザを開きます。
  2. 図内のビューを見つけます。
  3. 主キーを右クリックし、「エンティティキー」を確認します。チェックされます。
  4. すべての非主キーを複数選択します。 CtrlキーまたはShiftキーを使用します。
  5. [プロパティ]ウィンドウ(必要に応じてF4を押して表示)で、 "エンティティキー" Falseにドロップダウンします。
  6. 変更を保存します。
  7. Visual Studioを閉じて、再度開きます。 EF 6でVisual Studio 2013を使用しています 警告を消すにはこれをしなければなりませんでした。

ISNULL、NULLIF、またはCOALESCEの回避策を使用するために、ビューを変更する必要はありませんでした。データベースからモデルを更新すると、警告は再び表示されますが、VSを閉じて再度開くと消えます。デザイナで行った変更は保持され、更新の影響を受けません。

@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オプティマイザーはインデックスix_customerを使用せず、プライマリインデックスでテーブルスキャンを実行しますが、代わりに次の場合:

Group by CustomerId

使用

Group by IsNull(CustomerId, -1)

MS SQL(少なくとも2008)に正しいインデックスを計画に含めます。

If

この方法は私に適しています。プライマリキーフィールドにはISNULL()を使用し、フィールドがプライマリキーではなく、null不可の値を持つ必要がある場合はCOALESCE()を使用します。この例では、null不可の主キーを持つIDフィールドが生成されます。他のフィールドはキーではなく、Nullable属性として(None)を持っています。

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

現在のEntity Framework EDMジェネレーターは、ビュー内のすべてのNULL不可フィールドから複合キーを作成します。これを制御するには、ビューと基になるテーブル列を変更して、列を主キーの一部にしたくない場合に列をヌル可能に設定する必要があります。私が遭遇したように、EDMで生成されたキーがデータ複製の問題を引き起こしていたので、反対も真実です。そのため、EDMの複合キーにその列を含めるようにnull可能列をnull不可として定義する必要がありました。

ビューを取得するには、 one 主キー列のみを表示する必要がありました。最初のビューを指す2番目のビューを作成し、NULLIFを使用して型をNULL可能にしました。これにより、ビューに単一の主キーがあるとEFに思わせることができました。

EFが主キーのないエンティティを受け入れるとは思わないので、これがあなたに役立つかどうかはわかりません。

ROW_NUMBERを選択に組み込み、それを主キーとして設定し、モデル内の他のすべての列/メンバーを非主キーとして設定するために、主キーとなるものを混乱させたくない場合もお勧めします。

上記の問題のため、私はテーブル値関数を好みます。

これがある場合:

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

これを作成:

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

次に、ビューではなく関数をインポートします。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top