137

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

4

9 に答える 9

253

同じ問題がありましたが、これが解決策です。

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

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

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

例:

SELECT
  ISNULL(MyPrimaryID,-999) MyPrimaryID,
  NULLIF(AnotherProperty,'') AnotherProperty
  FROM ( ... ) AS temp
于 2010-04-26T17:00:42.057 に答える
68

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

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

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

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

Group by CustomerId

あなたが使う

Group by IsNull(CustomerId, -1)

これにより、MS SQL (少なくとも 2008 年) が適切なインデックスを計画に含めるようになります。

もしも

于 2012-05-04T19:24:57.167 に答える
9

この方法は私にはうまくいきます。主キーフィールドにISNULL()を使用し、フィールドを主キーにしない場合はCOALESCE()を使用しますが、null許容値を使用する必要もあります。この例では、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
于 2013-01-29T23:07:46.713 に答える
4

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

于 2009-10-07T18:54:56.900 に答える
3

主キーであるべきものを台無しにしたくない場合は、次のことをお勧めします。

  1. ROW_NUMBER選択に組み込む
  2. 主キーとして設定します
  3. モデル内の他のすべての列/メンバーを非プライマリとして設定します
于 2014-02-25T13:22:19.360 に答える
3

EdmGen の既知の問題のようです

于 2009-06-18T15:55:19.710 に答える
3

ビューを取得するには、主キー列を1 つだけ表示する必要がありました。最初のビューを指す 2 つ目のビューを作成し、NULLIF を使用して型を null 可能にしました。これは、ビューに主キーが1つしかないとEFに思わせるのに役立ちました。

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

于 2010-02-22T23:02:49.870 に答える
1

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

あなたがこれを持っている場合:

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

これを作成します:

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

次に、ビューではなく関数をインポートするだけです。

于 2014-08-03T20:05:28.403 に答える