我在我的 ASP.NET 项目中使用 SQL Server 2016 和 Entity Framework 6。为了初始化主菜单,我将 View 数据提取到 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 View 查询结果:
此外,我通过循环打印了“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 View 结果不一样!
我搞混了!谁知道这里发生了什么?
最佳答案
从 Entity Framework 使用时,views 有一个微妙的问题。
如果您有一个表,要将它与 EF 一起使用,您需要有一个主键 来唯一标识每一行。通常,这是一个单独的列,例如ID
或类似的东西。
对于 View ,您没有“主键”的概念 - View 仅包含某些表中的某些列。
因此,当 EF 映射 View 时,它找不到主键 - 因此,它将使用 View 中的所有不可为 null 的列作为“替代”主键。
我不知道你的情况是什么 - 你应该能够从 .edmx
模型中分辨出来。
当 EF 读取数据时,它会读取第一行并为其创建一个对象。
当 EF 读取第二行时,它注意到“主键”(数据集中所有不可为 null 的列的集合)与以前相同 - 因此它不会使用这些值创建新对象读取,但主键相同,因此它必须是与之前读取过的对象相同的对象,因此它会改用该对象。
所以问题真的是你不能在 View 上有明确的主键。
您可以调整您的 EF 模型,让 EF 清楚什么是真正的“主键”(您需要确保这些列都是不可空)- 或者您需要在您的 View 中添加类似“人工”主键的内容(使用例如 ROW_NUMBER() OVER()
构造)。
通过将此 RowNum
列添加到您的 View 中,它只是对行 1、2、....、n 进行编号,您将获得一个新的、不可为 null 的列,EF 会将其包含到“替换 PK”,并且由于这些数字是连续的,所以没有两行具有相同的“PK”值,因此不会被错误地替换为已经从数据库中读取的内容。
更新:@YounesJafari:您的映射完全支持我所说的;您的 View 的“主键”位于 (id
, parent_id
) - 对于您 View 的前两行,它们相同 -- 因此,EF 将取第一行 (id=0, parent_id=-1, abbreviation=en
) 两次 - 它会考虑 View 中的第二行 (id=0 , parent_id=-1, abbreviation=fa
) 与第一个相同(因为它们对 id
具有相同的值和 parent_id
) .....
关于c# - EF6 从数据库返回错误数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52578752/