C# 实体框架使用扩展方法引发异常
我的控制器中有以下代码:C# 实体框架使用扩展方法引发异常,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,我的控制器中有以下代码: public List<DockDoorViewModel> GetDoorViewModel() { List<DockDoorViewModel> doors = new List<DockDoorViewModel>(); for (int i = 1; i < 11; i++) { // This is where the Stack Trace is pointing to.
public List<DockDoorViewModel> GetDoorViewModel()
{
List<DockDoorViewModel> doors = new List<DockDoorViewModel>();
for (int i = 1; i < 11; i++)
{
// This is where the Stack Trace is pointing to.
DockDoorViewModel door = db.vwDockDoorDatas
.Where(x => x.DockNo == i)
.Select(x => x.ToDockDoorViewModel())
.FirstOrDefault();
if (door == null)
{
door = new DockDoorViewModel(i);
}
else
{
door.Items = db.vwDockDoorDatas
.Where(x => x.DockNo == i)
.Select(x => x.ToDockDoorItem())
.ToList();
}
doors.Add(door);
}
return doors;
}
我以前做过这种事情,所以我不知道我做错了什么?这是我第一次使用MVC5和EF6应用程序。在使用to方法之前,必须从SQL Server加载数据。您可以使用以下命令(例如)执行此操作:
door.Items = db.vwDockDoorDatas
.Where(x => x.DockNo == i)
.ToList() //Possibly use AsEnumerable() here instead as James says
.Select(x => x.ToDockDoorItem())
.ToList();
在使用to方法之前,必须从SQL Server加载数据。您可以使用以下命令(例如)执行此操作:
door.Items = db.vwDockDoorDatas
.Where(x => x.DockNo == i)
.ToList() //Possibly use AsEnumerable() here instead as James says
.Select(x => x.ToDockDoorItem())
.ToList();
错误消息告诉您需要知道的一切-EF无法将扩展方法转换为SQL,因此引发异常。您需要将查询从LINQ转换为实体到LINQ转换为对象,只需调用
AsEnumerable()
即可
DockDoorViewModel door = db.vwDockDoorDatas.Where(x => x.DockNo == i)
.AsEnumerable()
.Select(x => x.ToDockDoorViewModel())
.FirstOrDefault();
实际上,这会创建一个混合查询,其中AsEnumerable
之前的所有内容都被转换并作为SQL执行,其余部分在客户端和内存中执行
根据您的性能问题,再次查看您的查询时,您不必要地浏览了大量记录,您只关注第一条记录,因此为什么不直接浏览那条记录呢
vwDockDoorData entity = db.vwDockDoorDatas.Where(x => x.DockNo == i)
.FirstOrDefault();
DockDoorViewModel door = entity != null ? entity.ToDockDoorViewModel() : null;
对此的进一步改进是,在迭代记录之前只需过滤记录(给您一个开始/结束范围),例如
var doorDatas=db.vwDockDoorDatas.Where(x=>x.DockNo>=1&&x.DockNo错误消息告诉您真正需要知道的一切-EF无法将扩展方法转换为SQL,因此引发异常。您需要将查询从LINQ转换为实体到LINQ转换为对象,只需调用AsEnumerable()
即可
DockDoorViewModel door = db.vwDockDoorDatas.Where(x => x.DockNo == i)
.AsEnumerable()
.Select(x => x.ToDockDoorViewModel())
.FirstOrDefault();
实际上,这会创建一个混合查询,其中AsEnumerable
之前的所有内容都被转换并作为SQL执行,其余部分在客户端和内存中执行
根据您的性能问题,再次查看您的查询时,您不必要地浏览了大量记录,您只关注第一条记录,因此为什么不直接浏览那条记录呢
vwDockDoorData entity = db.vwDockDoorDatas.Where(x => x.DockNo == i)
.FirstOrDefault();
DockDoorViewModel door = entity != null ? entity.ToDockDoorViewModel() : null;
对此的进一步改进是,在迭代记录之前只需过滤记录(给您一个开始/结束范围),例如
var doorDatas=db.vwDockDoorDatas.Where(x=>x.DockNo>=1&&x.DockNo在这种情况下,选择aseneumerable
通常更好,因为您仍然保留延迟执行。在这种情况下,选择aseneumerable
通常更好,因为您仍然保留延迟执行。这很有效,谢谢。现在我只需要你知道为什么查询速度如此之慢。@RefractedPaladin很清楚,你的大部分查询现在都在内存中运行,因此根据结果集,结果可能会非常慢。你从SQL视图中提取了多少个结果?130个。大约15列。非“宽”虽然视图本身在ManagementStudio中运行需要4秒。但有一个问题,视图是否每次循环都必须“重新运行”?因此我添加了以下内容:var data=db.vwDockDoorDatas.ToList()
就在我的for
循环和性能飙升之前。我看到了你关于可枚举的注释,但这并没有改变任何事情。也许我不应该为此使用SQL视图。存储过程可能…@RefractedPaladin“每次我循环它时,视图都必须“重新运行”吗?”-这完全取决于循环的性质,你能举个例子吗?调用ToList
将返回你的整个结果集,所以我并不感到惊讶…这很有效,谢谢。现在我只需要弄清楚为什么它速度如此之慢。@RefractedPaladin很清楚,你的大部分查询现在都在内存中运行,这取决于结果集结果可能非常慢。您从SQL视图中提取了多少个结果?130个。大约15列。虽然视图本身在Management Studio中运行需要4秒,但不是“宽”。问题是,视图是否每次循环都必须“重新运行”?因此我添加了以下内容:var data=db.vwdockdordatas.ToList()
就在我的for
循环和性能飙升之前。我看到了你关于可枚举的注释,但这并没有改变任何事情。也许我不应该为此使用SQL视图。存储过程可能…@RefractedPaladin“每次我循环它时,视图都必须“重新运行”吗?”-这完全取决于循环的性质,你能举个例子吗?调用ToList
将返回你的整个结果集,所以我并不感到惊讶。。。