我有使用entityframework
的代码示例这个正在运作:
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);
}
但它不需要。所以我的问题是:
为什么将toIriable转换为toList包含数据到对象dbContext
?我知道在entityframework中我们正在使用扩展,但据我记得扩展返回值而不是将一个赋值给对象。
这是我的部分视图崩溃:
@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(" ")
}
错误讯息:
传递到字典中的模型项是类型的 &#39; BlogWeb.Models.Post&#39;,但这个字典需要一个模型项 输入&#39; System.Collections.Generic.List`1 [BlogWeb.Models.Tag]&#39;。
答案 0 :(得分:2)
当您致电dbContext.Posts.Include(a => a.Tags);
时,您只是在创建一个查询。没有元素来自数据库。
当您致电dbContext.Posts.Include(a => a.Tags).ToList();
时,您正在创建查询并执行它。元素被加载到内存中(包括Tags
属性)。
在第二个示例中,当您执行return View(dbContext.Posts.ToList());
时,内存中没有任何元素,并且当元素来自数据库时,您没有告诉包含Tags
。
在第一个示例中,您没有包含Tags
,但EF会保留以前加载的元素的轨迹以避免数据库查询,并且此元素在加载时包含Tags
。这就是为什么结果包括Tags
属性。
答案 1 :(得分:1)
当您将Linq方法链接在一起时,您将在幕后构建查询。添加Include(...)
告诉它在执行之前加入其他数据。当您致电ToList()
时,Linq查询将使用Include(...)
执行。
在第二个示例中,您没有执行查询,因此当您调用dbContext.Posts.ToList()
时,它没有缓存任何内容,而是在没有Include(...)
的情况下执行的另一个查询。
答案 2 :(得分:1)
请记住,在使用集合ToList
时,ToArray
,AsEnumerable
(我认为所有这些都是)都强制EF对数据库执行并将对象具体化回记忆。换句话说,如果你不迭代收集或调用其中一个,那么没有任何事情发生。
这个正在运作:
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();
的行将检索所有帖子以及每个帖子的标签。当您再调用return View(dbContext.Posts.ToList());
时,已经从数据库中检索了标签,除非您在一小段时间内添加了新帖子,否则不会有任何问题。
而这个不是:
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()
,只检索帖子。所以现在你有帖子但没有包含标签。
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不是命令对象,所以你不要这样使用它。