Ref*_*din 1 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.
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;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试运行Web应用程序时,我收到此异常:
异常详细信息:System.NotSupportedException:LINQ to Entities无法识别方法'DockDoorMonitor.Models.DockDoorViewModel ToDockDoorViewModel(DockDoorMonitor.Models.vwDockDoorData)'方法,并且此方法无法转换为商店表达式.
这是扩展方法:
public static class vwDockDoorDataExtensions
{
public static DockDoorViewModel ToDockDoorViewModel(this vwDockDoorData x)
{
DockDoorViewModel vm = null;
if (x != null)
{
vm = new DockDoorViewModel()
{
ID = x.ID,
DockNo = x.DockNo,
loadType = x.loadType,
LoadDescription = x.LoadDescription,
Name = x.Name,
LocationCode = x.LocationCode,
SACode = x.SACode
};
}
return vm;
}
public static DockDoorItem ToDockDoorItem(this vwDockDoorData x)
{
DockDoorItem vm = null;
if (x != null)
{
vm = new DockDoorItem()
{
ID = x.ItemNo,
Description = x.Description,
Quantity = x.Quantity,
UnitOfMeasure = x.UnitOfMeasure
};
}
return vm;
}
}
Run Code Online (Sandbox Code Playgroud)
我以前做过这种事情所以我没看到我做错了什么?这是我第一次使用MVC5和EF6应用程序.
错误消息告诉您确实需要知道的所有内容 - EF无法将您的扩展方法转换为SQL,因此会抛出异常.您需要查询的LINQ转换为实体到LINQ到对象,这可以用一个简单的调用来完成AsEnumerable()如
DockDoorViewModel door = db.vwDockDoorDatas.Where(x => x.DockNo == i)
.AsEnumerable()
.Select(x => x.ToDockDoorViewModel())
.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
实际上,它的作用是创建一个混合查询,其中所有内容都AsEnumerable被转换并作为SQL执行,其余部分在客户端和内存中执行.
根据你的性能问题,再次查看你的查询你不必要地浏览了很多记录,你只是在第一个记录之后,所以为什么不把它拉过来ie
vwDockDoorData entity = db.vwDockDoorDatas.Where(x => x.DockNo == i)
.FirstOrDefault();
DockDoorViewModel door = entity != null ? entity.ToDockDoorViewModel() : null;
Run Code Online (Sandbox Code Playgroud)
对此的进一步改进是在迭代记录之前简单地过滤记录(给你一个开始/结束范围),例如
var doorDatas = db.vwDockDoorDatas.Where(x => x.DockNo >= 1 && x.DockNo <= 11)
.ToList();
for (int i = 0; i < doorDatas.Count; i++)
{
// This is where the Stack Trace is pointing to.
DockDoorViewModel door = data.ToDockDoorViewModel();
if (door == null)
{
door = new DockDoorViewModel(i+1);
}
else
{
door.Items = data.ToDockDoorItem();
}
doors.Add(door);
}
Run Code Online (Sandbox Code Playgroud)
以上只需要一次DB.