我使用ASP.NET MVC Web应用程序来生成VSTS服务器的Back-Ups。
我的数据库有一堆嵌套表,在这种情况下,我正在访问一个名为" Project"的表。其中一个字段是ICollection,其中Backup是我的MVC中我的数据库/模型中的另一个表。项目在使用其中一个标准Controller模板创建的视图中加载得很好,但是,ICollection字段始终为null,即使有明确的"备份"在我的数据库中。
这是我的代码:
@model IEnumerable<Backup_Tool.Models.Site>
@functions{
public string GetLatest(Backup_Tool.Models.Project projekt)
{
if (projekt.Backup == null)
return "( - )";
DateTime time = DateTime.Now.AddYears(-500);
foreach (var back in projekt.Backup)
{
if (back.CreationTime > time)
time = back.CreationTime;
}
return $"{time.ToShortDateString()}";
} }
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Uri)
</td>
<td>
@Html.DisplayFor(modelItem => item.CreationTime)
</td>
<td>
@Html.DisplayFor(modelItem => item.Password)
</td>
<td>
@Html.DisplayFor(modelItem => item.User)
</td>
<td>
@foreach (var project in item.Projects)
{
<p>@Html.DisplayFor(m => project.Name)</p>
<i>@GetLatest(project)</i>
}
</td>
我是否还需要在顶部添加备份模型?实际上使用数据库上下文加载备份?
答案 0 :(得分:0)
没有您的实体类很难说,但很可能,您忽略了将virtual
关键字添加到您的集合属性中,并且也未能急切地加载它。
virtual
关键字是Entity Framework的延迟加载功能所必需的。 EF实际上创建了一个从您的实体类继承的代理类,然后覆盖导航属性以添加延迟加载逻辑。如果属性不是虚拟的,则不能覆盖它,因此无法添加必要的延迟加载逻辑。
但是,只是急切地加载集合,而不是依赖于延迟加载,这样做要好得多。虽然延迟加载很容易,但它也效率低下,并且经常导致逻辑错误不明显。例如,如果您执行此类操作,则会引发异常:
using (var context = new MyDbContext())
{
var foo = context.Foos.ToList();
}
foreach (var bar in foo.Bars) // where `Bars` is a lazy-loaded collection
{
...
}
当foreach
已经处理了上下文时,所以当EF尝试加载集合以便迭代它时,它将失败。如果你刚刚看到这个代码,那么错误在哪里并不明显,如果你想要可维护的代码,这是一个非常重要的事情。
无论如何,为了急切地加载集合,只需在初始查询中使用Include
即可。例如:
var project = context.Projects.Include(m => m.Backups).SingleOrDefault(m => m.Id == projectId);
注意,您必须使用SingleOrDefault
之类的内容,而不是Find
。 Find
尝试在命中数据库之前首先从上下文缓存加载实体,因此逻辑与其他实体的加入不兼容。
最后,您的GetLatest
功能既低效又多余。只需使用LINQ&#39; Max
函数:
@foreach (var project in item.Projects)
{
<p>@Html.DisplayFor(m => project.Name)</p>
<i>@(project.Backups.Max(m => m.CreationTime).ToShortDateString())</i>
}
此外,当您按原样返回值时,请避免字符串插值。例如,此代码:
return $"{time.ToShortDateString()}";
应该简单:
return time.ToShortDateString();
最终结果是相同的,但您只需要向堆中添加一个字符串而不是两个。虽然这是一件相当小的事情,但这样的低效率可能会在您的应用程序中出现大问题。