我正在使用EF数据库创建一个站点 - 首先使用ASP.NET MVC(我遵循本教程的所有内容:https://www.asp.net/mvc/overview/getting-started/database-first-development/creating-the-web-application),一切正常。
问题是在索引视图(记录列表)中我想从实体中删除其中一个字段。我不仅希望它隐藏在视图中,而是一起删除(问题是它拥有非常大的数据块,这使得列表的加载速度非常慢)。
在“编辑”视图中,我想显示并使用所有字段。
如果我从实体中删除一个字段,我会收到此错误:
实体类型XXX不是当前上下文模型的一部分。
on
return View(db.XXX.ToList());
我该怎么办?
答案 0 :(得分:1)
有几种方法可以解决这个问题。手头的问题是.ToList()。 如果您只是执行db.XXX,那么您将获得一个Enumerable,在枚举之前,它只是一组从数据库中获取数据的指令。一旦你调用.ToList(),它实际上就会从数据库中获取数据,这是花费这么长时间的步骤。
在我看来,最好的办法是定义一个ViewModel,它包含除了具有大量数据的字段之外的所有字段。
public class ViewModel
{
public ViewModel(){}
public int Id {get;set;}
public string OtherData {get;set;}
}
移动 db.XXX之外的View函数如下:
var initialDBObject = db.XXX;
从那里你可以获取你的Enumerable(它仍然是一组从数据库访问数据的指令)并将它选择到你的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
});
并创建一个匿名对象,但让一个匿名对象在View中工作有点复杂。
然后,您需要更新“索引视图”页面以使用ViewModel而不是原始数据库对象,您可以将其传递给:
View(viewModelObject.ToList());
将ViewModel命名为ViewModel之外的东西。像[DB Table Name] ViewModel或类似的东西。
如果数据库中有很多行,那么加载所有数据仍然需要很长时间,在这种情况下,您需要查看分页。
ToList()本身没有问题,原来的问题是由对ToList()的调用引起的,因为它是代码中的那个点,程序进入数据库并使用linq生成的查询以获取数据。如果你试图ToList()整个表的数据,或者像你的情况那样,有一个包含大量数据的列,可能需要一些时间,或者你可能会耗尽内存。
关于你必须包含在.Select()中的15列,是的,这很烦人。不幸的是,你不能在linq语句中使用构造函数,所以强制填充每一列。
定义ViewModel的另一种替代方法是打开.edmx设计图面,右键单击背景并添加New-> Entity,这可能更容易一些。您可以使用表XXX作为基础,给它一个不同的名称,如XXXViewModel或其他任何名称,然后删除包含大量数据的列。然后你只需要做db.XXXViewModel.ToList()。