问题描述
花了很多时间,但是仍然不明白如何避免在DbContext中进行缓存。
我在下面的一些简单案例的实体模型上附加了演示内容
问题是dbcontext缓存结果。例如,我有下面的代码用于查询数据库中的数据:
使用(TestContext ctx = new TestContext())
{
var res =(从ctx.Buildings.Where(x => x.ID == 1)中的b)
选择新的
{
b,
单位=从b中的f开始单位
选择新的
{
f,
人=从f中的p人
其中p。已存档==假
select p
}
})。AsEnumerable()。Select(x => xb).Single();
}
在这种情况下,一切都很好:我得到了我所得到的
但是,如果我在其后添加另一个查询,则查询建筑物中已将已存档标志设置为是的,我有接下来的事情,我真的无法理解:
- 我之前的结果,即 res ,将按数据添加(还会添加
,也将添加已存档== true的人员) - 新结果将包含所有人员的绝对值,无论存档等于什么
此查询的代码如下:
使用(TestContext ctx = new TestContext())
{
var res =(来自ctx.Buildings.W中的b,其中(x => x.ID == 1)
选择新的
{
b,
单位=从b中的f开始
选择新的
{
f,
人=来自f中的p人
,其中p.Archived ==假
select p
}
})。AsEnumerable()。Select(x => x.b).Single();
var newResult =(来自ctx.Buildings.Where(x => x.ID == 1)中的b)
选择新的
{
b,
单位=来自b中的f。单位
选择新的
{
f,
人=来自f中的p人
其中p。已归档== true
select p
}
})。AsEnumerable()。Select(x => xb).Single();
}
顺便说一句,我将 LazyLoadingEnabled 设置为false
有人知道如何解决此问题吗?我如何在查询中得到我在linq中真正写给实体的东西?
P.S。 @ p。
您可以使用方法。
var res =(从ctx.Buildings.Where中的b开始(x => x.ID == 1)
选择新的
{
b,
单位=从b中的f
选择新的
{
f,
人=来自f中的p人
其中p。已存档==假
选择p
}
})。AsNoTracking()。AsEnumerabe()。Select(x => xb).Single();
我还想指出,您的 AsEnumerable
弊大于利。如果删除它, Select(x => x.b)
将被转换为SQL。照原样,您正在选择所有内容,然后丢弃内存中除 x.b
之外的所有内容。
Spent a lot of time, but still cann't understand how to avoid caching in DbContext.
I attached below entity model of some easy case to demonstrate what I mean.
The problem is that dbcontext caching results. For example, I have next code for querying data from my database:
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();
}
In this case, everything is fine: I got what I want (Only persons with Archived == false).
But if I add another query after it, for example, query for buildings that have people that have Archived flag set to true, I have next things, that I really cann't understand:
- my previous result, that is res, will be added by data (therewill be added Persons with Archived == true too)
- new result will contain absolutely all Person's, no matter what Archived equals
the code of this query is next:
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();
}
By the way, I set LazyLoadingEnabled to false in constructor of TestContext.
Does anybody know how to workaround this problem? How can I have in my query what I really write in my linq to entity?
P.S. @Ladislav may be you can help?
You can use the AsNoTracking method on your query.
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();
I also want to note that your AsEnumerable
is probably doing more harm than good. If you remove it, the Select(x => x.b)
will be translated to SQL. As is, you are selecting everything, then throwing away everything but x.b
in memory.
这篇关于EF DbContext。如何避免缓存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!