C# 在选择列表中使用视图模型时,Linq to实体错误
我试图创建一个C# 在选择列表中使用视图模型时,Linq to实体错误,c#,.net,linq,linq-to-entities,C#,.net,Linq,Linq To Entities,我试图创建一个SelectList,方法是在单个视图模型实体中包装一大堆模型实体 我有一个视图模型类: public class ReferenceDocumentSelectionViewModel { public ReferenceDocument Document { get; set; } public int ID { get { return Document.ID; } } public String DisplayText {
SelectList
,方法是在单个视图模型实体中包装一大堆模型实体
我有一个视图模型类:
public class ReferenceDocumentSelectionViewModel
{
public ReferenceDocument Document { get; set; }
public int ID { get { return Document.ID; } }
public String DisplayText
{
get
{
return Document.DocumentNumber +
Document.Version +
Document.Revision +
Document.Sheet;
}
}
}
然后我尝试使用lambda表达式创建这些对象的列表:
var docs = _db.ReferenceDocuments
.Select(r => new ReferenceDocumentSelectionViewModel()
{
Document = r
});
在将它们分配到列表之前,请选择:
ReferenceDocList = new SelectList(docs.OrderBy(r => r.DisplayText),
"ID",
"DisplayText");
在我看来,我访问SelectList的方式如下:
@Html.DropDownListFor(model => model.SelectedReferenceDoc,
Model.ReferenceDocList,
"-Select-",
new { id = "ReferenceList" })
其中model.SelectedReferenceDoc
是另一个视图模型上的整数属性
我原以为这会起作用,但我得到了以下错误:
LINQ to中不支持指定的类型成员“DisplayText”
实体。仅初始值设定项、实体成员和实体导航
支持属性
帮忙
编辑:在进一步调查中,似乎是docs.OrderBy(r=>r.DisplayText)
导致了问题。如果我去掉它,它就可以正常工作了。知道为什么不允许这样做吗?因为DisplayText
不是映射属性,所以EF不知道如何将其转换为SQL。这就是为什么它会给你一个错误
您可以通过首先加载所有元素,在此处使用LINQ对对象进行排序
var docs = _db.ReferenceDocuments
.Select(r => new ReferenceDocumentSelectionViewModel()
{
Document = r
}).ToList();
然后在内存中对它们进行排序
ReferenceDocList = new SelectList(docs.OrderBy(r => r.DisplayText),
"ID",
"DisplayText");
或按每个属性排序
var docs = _db.ReferenceDocuments
.OrderBy(r => r.DocumentNumber)
.ThenBy(r => r.Version)
.ThenBy(r => r.Revision)
.ThenBy(r => r.Sheet)
.Select(r => new ReferenceDocumentSelectionViewModel()
{
Document = r
});
ReferenceDocList = new SelectList(docs,
"ID",
"DisplayText");
这种排序方式将在数据库中进行,比在内存中进行排序效率更高
因此,首选第二个选项。因为DisplayText
不是映射属性,EF不知道如何将其转换为SQL。这就是为什么它会给你一个错误
您可以通过首先加载所有元素,在此处使用LINQ对对象进行排序
var docs = _db.ReferenceDocuments
.Select(r => new ReferenceDocumentSelectionViewModel()
{
Document = r
}).ToList();
然后在内存中对它们进行排序
ReferenceDocList = new SelectList(docs.OrderBy(r => r.DisplayText),
"ID",
"DisplayText");
或按每个属性排序
var docs = _db.ReferenceDocuments
.OrderBy(r => r.DocumentNumber)
.ThenBy(r => r.Version)
.ThenBy(r => r.Revision)
.ThenBy(r => r.Sheet)
.Select(r => new ReferenceDocumentSelectionViewModel()
{
Document = r
});
ReferenceDocList = new SelectList(docs,
"ID",
"DisplayText");
这种排序方式将在数据库中进行,比在内存中进行排序效率更高
因此,第二个选项是首选的。另一个选项是.AsEnumerable(),太好了,谢谢您的解决方案!你能解释一下为什么这样做吗?第一个选项和第二个选项哪个更有效?之所以需要它,是因为传递到DropDownListFor
的数据仍然是IQueryable
。在该上下文中执行的任何排序都将尝试转换为SQL。因此,按DisplayText
排序将不起作用,因为该值仅通过C#code导出。仅按数据库列排序是一种解决方法,或者通过AsEnumerable
转换为普通的IEnumerable
是另一种方法(后者允许CLR对数据而不是数据库进行排序)。奇妙的Eranga,正是我所寻找的答案。谢谢你的评论@Jacob。另一个选择是.AsEnumerable()太好了,谢谢你的解决方案!你能解释一下为什么这样做吗?第一个选项和第二个选项哪个更有效?之所以需要它,是因为传递到DropDownListFor
的数据仍然是IQueryable
。在该上下文中执行的任何排序都将尝试转换为SQL。因此,按DisplayText
排序将不起作用,因为该值仅通过C#code导出。仅按数据库列排序是一种解决方法,或者通过AsEnumerable
转换为普通的IEnumerable
是另一种方法(后者允许CLR对数据而不是数据库进行排序)。奇妙的Eranga,正是我所寻找的答案。谢谢你的评论@Jacob。