私が話す自由がないいくつかの理由で、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
ISNULL(MyPrimaryID,-999) MyPrimaryID,
NULLIF(AnotherProperty,'') AnotherProperty
FROM ( ... ) AS temp
デザイナーを使用してこれを解決できました。
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)に正しいインデックスを計画に含めるようにします。
もし
この方法は私に適しています。主キーフィールドには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不可フィールドから複合キーを作成します。これを制御するには、ビューと基になるテーブル列を変更して、列を主キーの一部にしたくない場合に列を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])
次に、ビューではなく関数をインポートします。