我正在创建一个使用EF数据库的网站-首先与ASP。. NET MVC(我遵循所有本教程:https://www.asp.net/mvc/overview/getting-started/database-first-development/creating-the-web-application),一切都工作正常。
问题是,在索引视图(记录列表)中,我想从实体中删除一个字段。我不希望它只是隐藏在视图中,但所有一起删除(问题是,它持有一个非常大的数据块,这使得列表的加载非常慢)。
在"edit"视图中,我想显示并使用所有字段。
如果我从实体中删除一个字段,我得到这个错误:
实体类型XXX不是当前上下文的模型的一部分。
return View(db.XXX.ToList());
我能做什么?
有几种方法可以做到这一点。当前的问题是. tolist()。如果你只做db。XXX,那么您将获得一个Enumerable,在枚举之前,它只是一组从DB获取数据的指令。调用. tolist()后,它实际上会从DB中获取数据,这一步花费了很长时间。
在我看来,最好的办法是定义一个ViewModel,它包含所有字段,除了包含大量数据的字段。
public class ViewModel
{
public ViewModel(){}
public int Id {get;set;}
public string OtherData {get;set;}
}
移动db。
var initialDBObject = db.XXX;
从那里你可以把你的Enumerable(这仍然只是一组指令访问数据从你的DB),并选择它到你的ViewModel对象,像这样:
var viewModelObject = initialDBObject.Select(x=> new ViewModel
{
Id = x.Id;
OtherData = x.OtherData;
//do not add the large column of data to the ViewModel
});
这里发生的事情(在调用ToList()之前)是您正在修改linq在幕后生成的查询,以便从表XXX中获取数据(如果您在这行上放置一个断点并将鼠标悬停在initialDBObject上,您将看到生成的SQL)。调用ToList()后,查询将获取数据并将其插入ViewModel对象(而不是.edmx文件中定义的XXX对象),而不仅仅是从表XXX中获取数据。
你也可以
.Select(x=> new
{
Id,
OtherData
});
并创建一个匿名对象,但是让一个匿名对象在视图中工作有点复杂。
然后你需要更新索引视图页面使用ViewModel而不是原来的DB对象,你可以传递它像:
View(viewModelObject.ToList());
将ViewModel命名为ViewModel以外的东西。像[数据库表名]ViewModel或类似的东西。
如果数据库中有很多行,那么加载所有数据仍然需要很长时间,在这种情况下,您需要查看分页。
ToList()本身没有问题,最初的问题是由调用ToList()引起的,因为正是在代码中的这一点上,程序进入数据库并使用linq生成的查询来获取数据。如果您试图对整个表的数据进行ToList(),或者在您的情况下,有一个包含大量数据的列,这可能需要一些时间,或者您可能会耗尽内存。
关于必须包含在. select()中的15列,是的,这很烦人。不幸的是,您不能在linq语句中使用构造函数,因此必须填充每个列。
定义ViewModel的另一种选择(可能更简单)是打开.edmx设计界面,右键单击背景并添加New->Entity。您可以使用表XXX作为基,给它一个不同的名称,如XXXViewModel或其他,然后删除包含大量数据的列。然后只需要执行db.XXXViewModel.ToList()。