これを正しく理解しているかどうか見てみましょう。次のように定義された Users テーブルがあるように思えます。
public class User
{
//just assume that the following are all properties with {get;set;}
public int ID
public string Name
public string Email
public string Password
public string Address
//etc etc
}
次に、他のテーブルを次のように定義します。
public class SomeObject
{
public int ID
public string ObjectName
public string Category
//etc etc
public virtual User CreatedUser
public virtual User ModifiedUser
}
そして、ロードしたい 2 つのプロパティは、Name
and (またはそのようなもの)でEmail
あり、 の他の値はロードされません。私は近いですか?Password
Address
また、あなたが Code-First を使用しているかどうかもわかりませんが、それが私が今のところ想定していることです... (ほとんどの場合、それが私が最もよく知っているためです)
あなたがやりたいことは、次のようなものを追加することです:
public class SomeObject
{
//all the other stuff here...
public string CreatedUserName
public string CreatedUserEmail
public string ModifiedUserName
public string ModifiedUserEmail
}
しかし、実際に追加する必要があるのは、次のようなものです。
[NotMapped]
public string CreatedUserName
{
get { return CreatedUser.Name; }
}
これにより、EF は関係をたどってUser
レコードにアクセスし、Name
値を取得できるようになります。この[NotMapped]
属性により、EF はCreatedUserName
、テーブルで列を見つける必要がないことを認識できるようになりSomeObjects
ます。
これはあなたの質問に答えていますか?そうでない場合は、使用している EF のフレーバーとそれを使用して何をしようとしているのかについて、もう少し説明してみてください。;)
[OPのコメントに対する追加情報]
「ユーザー テーブルのスリムなバージョンをキャッシュし、他のプロパティをそのように検索する」ことには注意が必要です。これは、時期尚早の最適化のケースである可能性があります。つまり、User テーブルから UserNames と Emails をクエリしてキャッシュすることで、よりスムーズに動作するようにしていると思うかもしれませんが、実際には、必要以上に動作させているだけであるという結果になる可能性があります。
これがあなたの場合に確実であると言っているのではなく、最適化を試みる前に、EFが何をしているのか、プログラムのニーズが何であるかをよく理解しておく必要があります. そのためには、いくつかのテストを行い、ボトルネックがどこにあるかを確認する必要があります。たとえば、データベースへのネットワーク通信がコストのかかるボトルネックである場合、レコードのキャッシュを追加することでそれが改善される可能性があります。一方、メモリと CPU の制約によって速度が低下している場合は、キャッシュはお勧めできません。
もう 1 つ指摘しておきたいのは、このプログラムがデータベースに比較的近いサーバー (同じマシンまたは同じネットワーク上) で実行される場合、データベースに対して余分な呼び出しを行うべきであるということです。あまり気にする必要はありません。ただし、これがインターネットを介してトンネリングするデスクトップ アプリケーションであり、(たとえば) T1 接続を介してインターネットに接続されている単一のデータベース サーバーに到達する場合、データベースへの呼び出しはおそらく大きな問題になるでしょう。繰り返しますが、これらのケースのいずれかがあなたの状況に当てはまると言っているのではなく、EF が既に独自に行っているキャッシュに加えて追加のキャッシュを実装することを決定する前に、それらを調べる必要があるだけです。
そうは言っても、あなたに役立つかもしれない別の提案をさせてください。UserName
一度に複数のオブジェクトのandを取得することのみに関心がありEmail
、その時点でオブジェクトに対して他に何もしていない場合 (たとえば、ASP.NET MVC インデックス ビューでオブジェクトのリストを出力するなど)、私はそうします。Include
次のように、クエリで関連する User レコードをeager-loadするために使用することをお勧めします。
var query = MyDbContext.SomeObjects.Where(x => x.Category == "Foo")
.Include(x => x.CreatedUser)
.Include(x => x.ModifiedUser);
...または、次のように匿名クラスに必要なフィールドのみを選択するクエリを定義します。
var query = MyDbContext.SomeObjects.Where(x => x.Category == "Foo")
.Select(x => new {
ObjectName = x.ObjectName,
CreatedUserName = x.CreatedUser.Name,
CreatedUserEmail = x.CreatedUser.Email,
ModifiedUserName = x.ModifiedUser.Name,
ModifiedUserEmail = x.ModifiedUser.Email
});
最初のオプションは、EF に既に組み込まれているオブジェクト キャッシュ メカニズムを使用し、単一の select ステートメントを実行して、必要のない関連のないユーザー レコードをフェッチすることなく、必要なすべてのレコードをフェッチするという利点があります。2 番目のオプションは、必要なものだけをフェッチし、関心のない列を除外することで返されるデータをさらに削減する単一の select ステートメントであることからもメリットがあります。しかし、EF のオブジェクト キャッシュ メカニズムの恩恵を受けません (少なくともそうは思わないでください)。
一方、オブジェクトで複数のことを行っている場合、または関連するものを一度に 1 つまたは 2 つ (または比較的少数) のオブジェクトからのみ取得している場合はUserName
、Email
ナビゲーション プロパティに依存し、おそらく何かに似たことを行うことをお勧めします。先ほどデモンストレーションしました。