簡體   English   中英

實體框架返回錯誤數據

[英]Entity Framework returning bad data

我有一個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個名字!

簡而言之:

  1. 將EF發送投影DISTINCT查詢到SQL Server會返回正確的結果
  2. 讓EF選擇整個表,然后使用LINQ進行項目和DISTINCT,數據返回不正確的結果
  3. 為EF提供完全相同的查詢! 子彈#2生成並執行原始SQL查詢,返回正確的結果

下載實體框架源並單步調試許多Enumerator ,我發現了這個問題。

Shaper.HandleEntityAppendOnly方法( 在此處找到 )中,在第187行調用Context.ObjectStateManager.FindEntityEntry方法。 令我驚訝的是,返回了一個非null值! 等一下,不應該有任何緩存結果,因為我要返回所有行?!

那是我發現我的桌子沒有主鍵的時候!

在我的辯護中,該表實際上是我正在使用的視圖的緩存,我只是做了一個 SELECT * INTO CACHETABLE FROM USERVIEW

然后我查看實體框架認為哪個列是我的主鍵(他們稱之為單鍵),恰好它們所選擇的列只有...... 鼓請 ... 5個獨特的值!

當我看到EF生成的模型時,果然! 該列被指定為主鍵。 我將密鑰更改為相應的列,現在一切正常!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM