4

多くの時間を費やしましたが、DbContext でのキャッシュを回避する方法をまだ理解できません。

私が何を意味するかを示すために、いくつかの簡単なケースのエンティティモデルを以下に添付しました。

問題は、dbcontext キャッシュが発生することです。たとえば、データベースからデータをクエリするための次のコードがあります。

using (TestContext ctx = new TestContext())
{
   var res = (from b in ctx.Buildings.Where(x => x.ID == 1)
             select new
             {
                b,
                flats = from f in b.Flats
                        select new
                        {
                           f,
                           people = from p in f.People
                           where p.Archived == false
                           select p
                        }
             }).AsEnumerable().Select(x => x.b).Single();

}

この場合、すべて問題ありません: 欲しいものを手に入れました (Archived == false の人のみ)。

しかし、その後に別のクエリを追加すると、たとえば、Archived フラグが true に設定されている人々がいる建物のクエリを追加すると、次のことがわかりません。

  1. 私の以前の結果、つまりresは、データによって追加されます (アーカイブされた == true の人物も追加されます)
  2. 新しい結果には、Archived が何に等しいかに関係なく、完全にすべての Person が含まれます

このクエリのコードは次のとおりです。

using (TestContext ctx = new TestContext())
{
   var res = (from b in ctx.Buildings.Where(x => x.ID == 1)
             select new
             {
                b,
                flats = from f in b.Flats
                        select new
                        {
                           f,
                           people = from p in f.People
                           where p.Archived == false
                           select p
                        }
             }).AsEnumerable().Select(x => x.b).Single();


    var newResult = (from b in ctx.Buildings.Where(x => x.ID == 1)
              select new
              {
                  b,
                  flats = from f in b.Flats
                          select new
                          {
                             f,
                             people = from p in f.People
                             where p.Archived == true
                             select p
                           }
               }).AsEnumerable().Select(x => x.b).Single();
            }

ちなみに、 TestContext のコンストラクタでLazyLoadingEnabledを false に設定しています。

この問題を回避する方法を知っている人はいますか? linq to entityに実際に書いたものをクエリに含めるにはどうすればよいですか?

PS @Ladislav お手伝いできることはありますか?

エンティティ モデル

4

2 に答える 2

9

クエリでAsNoTrackingメソッドを使用できます。

var res = (from b in ctx.Buildings.Where(x => x.ID == 1)
         select new
         {
            b,
            flats = from f in b.Flats
                    select new
                    {
                       f,
                       people = from p in f.People
                       where p.Archived == false
                       select p
                    }
         }).AsNoTracking().AsEnumerabe().Select(x => x.b).Single();

また、あなたAsEnumerableはおそらく善よりも害を及ぼしていることに注意したいと思います。削除すると、 はSelect(x => x.b)SQL に変換されます。そのまま、すべてを選択してから、メモリ内以外のすべてを破棄x.bします。

于 2013-07-23T14:20:30.360 に答える
2

次のようなことを試しましたか:

ctx.Persons.Where(x => x.Flat.Building.Id == 1 && x.Archived == false);

=====編集=====

この場合、あなたのアプローチは、私見ですが、本当に危険だと思います。実際、クエリを解釈した結果のデータではなく、EF によって読み込まれたデータを処理してクエリを解釈します。ある日、EF の変更によってポリシーが読み込まれる場合 (たとえば、予測プリロードを使用する場合)、アプローチは「あなたを壁に送り込みます」。

あなたの目標のために、「filterd」エンティティを構築するために必要なデータを熱心にロードする必要があります。つまり、建物を選択してから、foreach Flat でアーカイブされていない人物を選択します。

もう 1 つの解決策は、"UnitOfWork" のような設計で別々のコンテキストを使用することです。

于 2013-07-23T14:48:14.463 に答える