花了很多时间,但仍然无法理解如何避免在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的人的建筑物,我接下来的事情,我真的无法理解:
此查询的代码如下:
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中写入实体的内容?
P.S。 @Ladislav可能会帮忙吗?
答案 0 :(得分:8)
您可以在查询中使用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
之外的所有内容。
答案 1 :(得分:2)
ctx.Persons.Where(x => x.Flat.Building.Id == 1 && x.Archived == false);
=====编辑=====
在这种情况下,我认为你接近的是,imho,真的很危险。实际上,您处理由EF加载的数据来解释您的查询,而不是解释您的查询的数据。如果有一天EF更改是加载策略(例如预加载预测),您的方法将“将您送到墙上”。
为了您的目标,您必须急于加载构建“过滤”实体所需的数据。那就是选择建筑物,然后预选Flat选择非存档的人。
另一种解决方案是在“UnitOfWork”中使用过于单独的上下文,如设计。