EF6从数据库返回错误的数据

时间:2018-09-30 14:22:19

标签: c# sql sql-server entity-framework

我在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视图查询结果:

enter image description here

此外,我还通过循环打印了'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);

这是结果:

enter image description here

比较两个结果时,Entity Framework中的缩写列数据与SQL Server视图结果不同!

我混了!谁知道这里发生了什么?

编辑: 映射细节 enter image description here

1 个答案:

答案 0 :(得分:4)

在Entity Framework中使用时,视图存在一个细微的问题。

如果有一个表,要与EF一起使用,则需要有一个主键来唯一地标识每一行。通常,这是一列,例如ID或类似的东西。

对于视图,您没有“主键”的概念-视图仅包含某些表中的某些列。

因此,当EF映射视图时,它找不到主键-因此,它将使用该视图中的所有不可空列作为“替代”主键。

我不知道您的情况是什么-您应该可以从.edmx模型中看出来。

当EF去读取数据时,它将读取第一行并为此创建一个对象。

当EF读取第二行时,它会注意到“主键”(数据集中所有非空列的集合)与以前相同-因此,它不会打扰使用这些值创建新对象可以读取,但是主键是相同的,因此它必须是与以前已经读取过的对象相同的对象,因此它改用该对象。

所以问题实际上是您在视图上不能有显式主键。

您可以调整EF模型以向EF清楚什么是真正的“主键”(您需要确保这些列都不可为空)-或者您需要在视图中添加“人工”主键之类的内容(例如使用ROW_NUMBER() OVER()构造)。

通过将此RowNum列添加到仅对第1、2,...,n行进行编号的视图中,您将获得一个新的,不可为空的列,EF将其包含在“替代PK”中”,并且由于这些数字是连续的,因此没有两行具有相同的“ PK”值,因此不会错误地将其替换为已经从数据库中读取的内容。

更新:@YounesJafari:您的映射完全支持我的意思;您的视图的“主键”位于(idparent_id)上;对于视图的前两行,它们是相同的-因此,EF将两次占据第一行(id=0, parent_id=-1, abbreviation=en)-它将认为视图(id=0, parent_id=-1, abbreviation=fa)中的第二行与第一行相同(因为它们具有 idparent_id的相同值).....