我在ASP.NET项目中使用SQL Server 2016和Entity Framework 6。要初始化主菜单,我将视图数据以C#语言获取到List变量:
using (var db = new DBEntities())
{
ImageGroupList.AddRange(db.vw_image_groups.OrderBy(x => x.id)
.ThenBy(x => x.abbreviation).ToList());
但是结果与我在SQL Server Management Studio中看到的结果不同。
这是SSMS中的SQL Server视图查询结果:
此外,我还通过循环打印了'ImageGroupList'值:
foreach (var item in ImageGroupList)
{
System.Diagnostics.Debug.WriteLine(item.id + ", " + item.parent_id + ", " + item.abbreviation + ", " + item.text + ", " + item.member_count + ", " + item.type + ", " + item.order_index);
这是结果:
比较两个结果时,Entity Framework中的缩写列数据与SQL Server视图结果不同!
我混了!谁知道这里发生了什么?
答案 0 :(得分:4)
在Entity Framework中使用时,视图存在一个细微的问题。
如果有一个表,要与EF一起使用,则需要有一个主键来唯一地标识每一行。通常,这是一列,例如ID
或类似的东西。
对于视图,您没有“主键”的概念-视图仅包含某些表中的某些列。
因此,当EF映射视图时,它找不到主键-因此,它将使用该视图中的所有不可空列作为“替代”主键。
我不知道您的情况是什么-您应该可以从.edmx
模型中看出来。
当EF去读取数据时,它将读取第一行并为此创建一个对象。
当EF读取第二行时,它会注意到“主键”(数据集中所有非空列的集合)与以前相同-因此,它不会打扰使用这些值创建新对象可以读取,但是主键是相同的,因此它必须是与以前已经读取过的对象相同的对象,因此它改用该对象。
所以问题实际上是您在视图上不能有显式主键。
您可以调整EF模型以向EF清楚什么是真正的“主键”(您需要确保这些列都不可为空)-或者您需要在视图中添加“人工”主键之类的内容(例如使用ROW_NUMBER() OVER()
构造)。
通过将此RowNum
列添加到仅对第1、2,...,n行进行编号的视图中,您将获得一个新的,不可为空的列,EF将其包含在“替代PK”中”,并且由于这些数字是连续的,因此没有两行具有相同的“ PK”值,因此不会错误地将其替换为已经从数据库中读取的内容。
更新:@YounesJafari:您的映射完全支持我的意思;您的视图的“主键”位于(id
,parent_id
)上;对于视图的前两行,它们是相同的-因此,EF将两次占据第一行(id=0, parent_id=-1, abbreviation=en
)-它将认为视图(id=0, parent_id=-1, abbreviation=fa
)中的第二行与第一行相同(因为它们具有 id
和parent_id
的相同值).....