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 的人)。

但是,如果我在其后添加另一个查询,例如,查询将存档标志设置为 true 的人的建筑物,我会遇到以下事情,我真的无法理解:

  1. 我之前的结果,即res,将由数据添加(也会添加带有 Archived == true 的 Persons )
  2. 新结果将绝对包含所有 Person 的,无论 Archived 等于什么

此查询的代码如下:

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 更改加载策略(例如使用预测性预加载),您的方法将“将您发送到墙中”。

为了您的目标,您将不得不急切地加载构建“过滤”实体所需的数据。即选择建筑物,然后 foreach Flat 选择未归档的人员。

另一种解决方案是在类似“UnitOfWork”的设计中使用过于独立的上下文。

于 2013-07-23T14:48:14.463 回答