はい、射影を使用して列のサブセットのみを返すことができます。
var result = from x in context.LargeTable
select new { x.Id, x.Name };
問題:投影と積極的な読み込みが一緒に機能しません。プロジェクションまたはカスタム結合の使用を開始すると、クエリの形状が変更され、使用できなくなりますInclude
(EFはそれを無視します)。このようなシナリオでの唯一の方法は、予測される結果セットにリレーションを手動で含めることです。
var result = from x in context.LargeTable
select new {
Id = x.Id,
Name = x.Name,
// You can filter or project relations as well
RelatedEnitites = x.SomeRelation.Where(...)
};
特定のタイプに投影することもできますが、その特定のタイプをマップしてはなりません(たとえばLargeTable
、私のサンプルからエンティティにプロジェクトすることはできません)。マップされたエンティティへの射影は、Linq-to-objectsのマテリアライズされたデータに対してのみ実行できます。
編集:
EFがどのように機能するかについてはおそらく誤解があります。EFはエンティティの上で機能します-エンティティはあなたがマッピングしたものです。500列をエンティティにマップする場合、EFは定義したとおりにそのエンティティを使用するだけです。これは、クエリがエンティティをロードし、永続化することでエンティティが保存されることを意味します。
なぜこのように機能するのですか?エンティティはアトミックデータ構造と見なされ、そのデータは1回だけロードおよび追跡できます。これは、変更をデータベースに正しく永続化する機能の重要な機能です。必要に応じて列のサブセットだけをロードする必要がないという意味ではありませんが、列のサブセットをロードしても元のエンティティが定義されないことを理解する必要があります。これは、エンティティ内のデータの任意のビューと見なされます。このビューは追跡されず、追加の作業なしにデータベースに永続化することはできません(EFが投影の起点に関する情報を保持していないためです)。
EFは、エンティティをマップする機能にもいくつかの追加の制約を課します
- 通常、各テーブルは1回だけマップできます。なんで?繰り返しになりますが、テーブルを異なるエンティティに複数回マッピングすると、それらのエンティティを正しく永続化する機能が損なわれる可能性があります。たとえば、非キー列が2回マッピングされ、同じレコードにマッピングされた両方のエンティティのインスタンスをロードした場合、マッピングされた値のどちらを使用しますか。変更を保存しますか?
- テーブルを複数回マッピングできる2つの例外があります
- 階層ごとのテーブルの継承-これは、継承階層で定義された複数のエンティティタイプのレコードをテーブルに含めることができるマッピングです。階層内の基本エンティティにマップされた列は、すべてのエンティティで共有する必要があります。すべての派生エンティティタイプは、特定のプロパティにマップされた独自の列を持つことができます(他のエンティティタイプでは、これらの列は常に空になります)。派生プロパティの列を複数のエンティティ間で共有することはできません。また、レコードに格納されているエンティティタイプをEFに通知するdiscriminatorと呼ばれる追加の列が1つ必要です。この列は、タイプdiscriminatorとして既にマップされているため、プロパティとしてマップできません。
- テーブル分割-これは、単一テーブルマッピングの制限に対する直接的な解決策です。これにより、いくつかの制約付きでテーブルを複数のエンティティに分割できます。
- エンティティ間には1対1の関係が必要です。コアデータのロードに使用される中央エンティティが1つあり、他のすべてのエンティティには、このエンティティからナビゲーションプロパティを介してアクセスできます。積極的な読み込み、遅延読み込み、明示的な読み込みは正常に機能します。
- 関係は実数1-1であるため、両方の部分または関係が常に存在する必要があります。
- エンティティは、キー以外のプロパティを共有してはなりません。変更可能な各プロパティは1回だけマップされるため、この制約によって最初の問題が解決されます。
- 分割テーブルのすべてのエンティティには、マップされたキープロパティが必要です
- 他のエンティティにはマップされた必要な列を含めることができるため、挿入にはオブジェクトグラフ全体を入力する必要があります
Linq-to-Sqlには、列を遅延読み込みとしてマークする機能も含まれていますが、この機能は現在EFでは使用できません。この機能に投票できます。
それは最適化のためのあなたのオプションにつながります
- 投影法を使用して、エンティティの読み取り専用の「ビュー」を取得します
- この回答の前の部分で示したように、Linqクエリでそれを行うことができます
- データベースビューを作成し、それを新しい「エンティティ」としてマップできます
- EDMXでは、「クエリの定義」または「クエリビュー」を使用して、マッピングにSQLまたはESQLプロジェクションをカプセル化することもできます。
- テーブル分割を使用する
- EDMXを使用すると、問題なくテーブルを多くのエンティティに分割できます
- コードを最初に使用するとテーブルを分割することもできますが、テーブルを3つ以上のエンティティに分割する場合は、いくつかの問題があります(各エンティティタイプには、分割テーブルから他のすべてのエンティティタイプへのナビゲーションプロパティが必要です。これにより、使用が非常に困難になります。 )。