加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 实体框架返回错误数据

发布时间:2020-12-15 08:05:10 所属栏目:百科 来源:网络整理
导读:我有一个Entity Framework 6.1项目,它正在查询SQL Server 2012数据库表并返回不正确的结果. 为了说明发生了什么,我创建了两个应该具有完全相同结果的查询.表ProjectTable有23列和20500行: var test1 = db.ProjectTable .GroupBy(t = t.ProjectOwner) .Selec
我有一个Entity Framework 6.1项目,它正在查询SQL Server 2012数据库表并返回不正确的结果.

为了说明发生了什么,我创建了两个应该具有完全相同结果的查询.表ProjectTable有23列和20500行:

var test1 = db.ProjectTable
    .GroupBy(t => t.ProjectOwner)
    .Select(g => g.Key)
    .ToArray();

var test2 = db.ProjectTable
    .ToArray()
    .GroupBy(t => t.ProjectOwner)
    .Select(g => g.Key)
    .ToArray();

查询旨在获取表中所有不同项目所有者的列表.第一个查询在SQL Server上执行繁重的工作,第二个查询将整个表下载到内存中,然后在客户端处理它.

第一个变量test1的长度约为300个.第二个变量test2的长度为5.

以下是EF生成的原始SQL查询:

-- test1
SELECT [Distinct1].[ProjectOwner] AS [ProjectOwner]
FROM ( SELECT DISTINCT
       [Extent1].[ProjectOwner] AS [ProjectOwner]
       FROM [dbo].[ProjectTable] as [Extent1]
     ) AS [Distinct1]

-- test2
SELECT Col1,Col2 ... ProjectOwner,... Col23
FROM [dbo].[ProjectTable]

当我运行此查询并分析返回的实体时,我注意到返回了完整的20500行,但ProjectOwner列被仅有5个不同用户中的一个覆盖!

var test = db.ProjectTable.ToArray();

我想也许是SQL Server,所以我做了一个数据包跟踪并在TDS上过滤.随机查看原始流我看到许多名称不在5的列表中,所以我知道数据正在通过线路正确发送.

如何查看EF获取的原始数据?有什么东西可能会搞乱缓存并拉出不正确的结果吗?

如果我在SSMS或Visual Studio中运行查询,则返回的列表是正确的.只有EF有这个问题.

编辑

好的,我添加了另一项测试,以确保我的理智得到控制.
我接受了test2原始sql查询并执行了以下操作:

var test3 = db.Database
    .SqlQuery<ProjectTable>(@"SELECT Col1..Col23")
    .ToArray()
    .Select(t => t.ProjectOwner)
    .Distict()
    .ToArray();

我得到了正确的300个名字!

简而言之:

>让EF向SQL Server发送预测的DISTINCT查询返回正确的结果
>让EF选择整个表,然后使用LINQ进行投影和DISTINCT,数据返回不正确的结果
>给予EF完全相同的查询!子弹#2生成并执行原始SQL查询,返回正确的结果

解决方法

下载实体框架源并单步执行许多枚举器后,我发现了这个问题.

在Shaper.HandleEntityAppendOnly方法(found here)中,在第187行调用Context.ObjectStateManager.FindEntityEntry方法.令我惊讶的是,返回了一个非null值!等一下,不应该有任何缓存结果,因为我要返回所有行?!

那是我发现我的桌子没有主键的时候!

在我的辩护中,该表实际上是一个我正在使用的视图的缓存,我只是做了一个SELECT * INTO CACHETABLE FROM USERVIEW

然后,我查看实体框架认为哪个列是我的主键(他们称之为单键),它恰好是他们选择的列只有…鼓请… 5个独特的值!

当我看到EF生成的模型时,果然!该列被指定为主键.我将密钥更改为相应的列,现在一切正常!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读