为什么将 IQueryable 转换为 .toList() 将数据包含到对象 DbContext?
Why casting IQueryable to .toList() include data to object DbContext?
我有一个使用实体框架的代码示例
这个有效:
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
dbContext.Posts.Include(a => a.Tags).ToList();
return View(dbContext.Posts.ToList());
}
而这个不是:
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
dbContext.Posts.Include(a => a.Tags);
return View(dbContext.Posts.ToList());
}
所以我不明白,为什么只转换到List
就足以包含来自模型(List<Tags>
)的标签,如果是这样我会理解,这也很好(我正在使用它!问题与代码格式无关!):
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
var model=dbContext.Posts.Include(a => a.Tags).ToList();
return View(model);
}
但这并不需要。所以我的问题是:
为什么将 IQueryable 转换为 toList 会将数据包含到对象 dbContext
? 我知道在实体框架中我们正在使用扩展,但据我所知扩展 return值未将一个分配给对象。
这是我崩溃的局部视图:
@using BlogWeb.Models
@model Post
<h1>@Model.Title</h1>
<p class="lead">
by <a href="#">1234</a>
</p>
<hr>
<p>@Model.Created</p>
<p class="lead">
@Model.Body
</p>
@Html.Partial("_Tags", Model.Tags) -<< this is what is throwing error
<hr>
这是部分标签视图
@using BlogWeb.Models
@model List<Tag>
@foreach (Tag tag in Model)
{
@Html.Label('#' + tag.TagName)
@Html.Raw(" ")
}
错误信息:
The model item passed into the dictionary is of type
'BlogWeb.Models.Post', but this dictionary requires a model item of
type 'System.Collections.Generic.List`1[BlogWeb.Models.Tag]'.
当您将这些 Linq 方法链接在一起时,您就是在幕后构建一个查询。添加 Include(...)
告诉它在执行之前加入其他数据。当您调用 ToList()
时,将使用 Include(...)
.
执行 Linq 查询
在第二个示例中,您没有执行查询,因此当您调用 dbContext.Posts.ToList()
时,它没有缓存任何内容,而是在没有 Include(...)
.[= 的情况下执行的不同查询15=]
请记住,在使用 Collections ToList
、ToArray
、AsEnumerable
(我认为这是所有这些)时,所有这些都会强制 EF 对数据库执行并具体化对象回到记忆中。换句话说,如果您不遍历集合或调用其中之一,则什么也不会发生。
This one is working:
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
dbContext.Posts.Include(a => a.Tags).ToList();
return View(dbContext.Posts.ToList());
}
EF 在内部跟踪实体的状态。因此,代码 dbContext.Posts.Include(a => a.Tags).ToList();
行将检索所有 post 以及每个 post 的标签。当您随后调用 return View(dbContext.Posts.ToList());
时,标签已经从数据库中检索到,除非您在那几分之一秒内添加了一个新的 post,否则不会有任何问题。
and this one is not:
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
dbContext.Posts.Include(a => a.Tags);
return View(dbContext.Posts.ToList());
}
行 dbContext.Posts.Include(a => a.Tags);
告诉 EF 包含标签但不对其执行任何其他操作,您实际上只是丢弃了您正在处理的命令。然后调用 dbContext.Posts.ToList()
,它只检索 post。所以现在你有帖子但没有包含标签。
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
var model = dbContext.Posts.Include(a => a.Tags).ToList();
return View(model);
}
这是使用 EF 的方式,因为现在您不会丢弃 DbSet<t>
上的结果。所有 EF 扩展命令都会具体化某些内容,您应该使用该结果。 DbSets<T>
本身并不是为了跟踪对它们执行的操作(EF 实体跟踪除外,但这不是我所说的)。 DbSet 不是一个命令对象,所以你不应该这样使用它。
当您调用 dbContext.Posts.Include(a => a.Tags);
时,您只是在创建一个查询。没有元素来自数据库。
当您调用 dbContext.Posts.Include(a => a.Tags).ToList();
时,您正在创建并执行查询。元素加载到内存中(包括Tags
属性)。
在您的第二个示例中,当您执行 return View(dbContext.Posts.ToList());
时,内存中没有任何元素,并且当元素来自数据库时,您并没有告诉要包含 Tags
。
在您的第一个示例中,您没有包括 Tags
,但 EF 会跟踪先前加载的元素以避免数据库查询,并且加载的元素包括 Tags
。这就是为什么结果包括 Tags
属性.
我有一个使用实体框架的代码示例
这个有效:
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
dbContext.Posts.Include(a => a.Tags).ToList();
return View(dbContext.Posts.ToList());
}
而这个不是:
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
dbContext.Posts.Include(a => a.Tags);
return View(dbContext.Posts.ToList());
}
所以我不明白,为什么只转换到List
就足以包含来自模型(List<Tags>
)的标签,如果是这样我会理解,这也很好(我正在使用它!问题与代码格式无关!):
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
var model=dbContext.Posts.Include(a => a.Tags).ToList();
return View(model);
}
但这并不需要。所以我的问题是:
为什么将 IQueryable 转换为 toList 会将数据包含到对象 dbContext
? 我知道在实体框架中我们正在使用扩展,但据我所知扩展 return值未将一个分配给对象。
这是我崩溃的局部视图:
@using BlogWeb.Models
@model Post
<h1>@Model.Title</h1>
<p class="lead">
by <a href="#">1234</a>
</p>
<hr>
<p>@Model.Created</p>
<p class="lead">
@Model.Body
</p>
@Html.Partial("_Tags", Model.Tags) -<< this is what is throwing error
<hr>
这是部分标签视图
@using BlogWeb.Models
@model List<Tag>
@foreach (Tag tag in Model)
{
@Html.Label('#' + tag.TagName)
@Html.Raw(" ")
}
错误信息:
The model item passed into the dictionary is of type 'BlogWeb.Models.Post', but this dictionary requires a model item of type 'System.Collections.Generic.List`1[BlogWeb.Models.Tag]'.
当您将这些 Linq 方法链接在一起时,您就是在幕后构建一个查询。添加 Include(...)
告诉它在执行之前加入其他数据。当您调用 ToList()
时,将使用 Include(...)
.
在第二个示例中,您没有执行查询,因此当您调用 dbContext.Posts.ToList()
时,它没有缓存任何内容,而是在没有 Include(...)
.[= 的情况下执行的不同查询15=]
请记住,在使用 Collections ToList
、ToArray
、AsEnumerable
(我认为这是所有这些)时,所有这些都会强制 EF 对数据库执行并具体化对象回到记忆中。换句话说,如果您不遍历集合或调用其中之一,则什么也不会发生。
This one is working:
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
dbContext.Posts.Include(a => a.Tags).ToList();
return View(dbContext.Posts.ToList());
}
EF 在内部跟踪实体的状态。因此,代码 dbContext.Posts.Include(a => a.Tags).ToList();
行将检索所有 post 以及每个 post 的标签。当您随后调用 return View(dbContext.Posts.ToList());
时,标签已经从数据库中检索到,除非您在那几分之一秒内添加了一个新的 post,否则不会有任何问题。
and this one is not:
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
dbContext.Posts.Include(a => a.Tags);
return View(dbContext.Posts.ToList());
}
行 dbContext.Posts.Include(a => a.Tags);
告诉 EF 包含标签但不对其执行任何其他操作,您实际上只是丢弃了您正在处理的命令。然后调用 dbContext.Posts.ToList()
,它只检索 post。所以现在你有帖子但没有包含标签。
public ActionResult Index()
{
BlogContext dbContext = new BlogContext();
var model = dbContext.Posts.Include(a => a.Tags).ToList();
return View(model);
}
这是使用 EF 的方式,因为现在您不会丢弃 DbSet<t>
上的结果。所有 EF 扩展命令都会具体化某些内容,您应该使用该结果。 DbSets<T>
本身并不是为了跟踪对它们执行的操作(EF 实体跟踪除外,但这不是我所说的)。 DbSet 不是一个命令对象,所以你不应该这样使用它。
当您调用 dbContext.Posts.Include(a => a.Tags);
时,您只是在创建一个查询。没有元素来自数据库。
当您调用 dbContext.Posts.Include(a => a.Tags).ToList();
时,您正在创建并执行查询。元素加载到内存中(包括Tags
属性)。
在您的第二个示例中,当您执行 return View(dbContext.Posts.ToList());
时,内存中没有任何元素,并且当元素来自数据库时,您并没有告诉要包含 Tags
。
在您的第一个示例中,您没有包括 Tags
,但 EF 会跟踪先前加载的元素以避免数据库查询,并且加载的元素包括 Tags
。这就是为什么结果包括 Tags
属性.