0

EF4.4 には約 12 個のテーブルがあり、共通のユーザー ルックアップ テーブルから 2 つのプロパティを読み込む必要があります (実際にはこれを 2 回実行します - CreatedUser 用に 1 回、ModifiedUser 用に 1 回)。

ユーザーテーブルにはnullではない他の列があり、(クエリ結果を節約するために)それらを削除しようとすると、EFはそれらをマップする必要があると不平を言います。そのテーブルに挿入するつもりはないので、このエラーを回避する方法はありますか?選択に使用するだけです。

素晴らしいのは、FK によって既に参照プロパティになっていることです。それをカスタム ビューに変更する場合は、これらの 12 個すべてをビューとこのテーブルへのリンクに手動でやり直す必要があります。これは世界の終わりではありませんが、それを回避しようとしています :)

4

1 に答える 1

0

これを正しく理解しているかどうか見てみましょう。次のように定義された 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 つのプロパティは、Nameand (またはそのようなもの)でEmailあり、 の他の値はロードされません。私は近いですか?PasswordAddress

また、あなたが 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 つ (または比較的少数) のオブジェクトからのみ取得している場合はUserNameEmailナビゲーション プロパティに依存し、おそらく何かに似たことを行うことをお勧めします。先ほどデモンストレーションしました。

于 2013-07-03T21:06:06.747 に答える