2012-07-17 120 views
11

我們有一個客戶非常大的表超過列(我知道有人做的!)使用EF代碼第一次

許多列實際上外鍵與其他表數據庫選擇特定的列

我們也有要求急切加載一些相關的表格。

Linq to SQL或Dynamic Linq有什麼方法可以指定從數據庫中檢索哪些列? 我找的,實際上,在生成SQL語句這種影響一個LINQ聲明:

SELECT Id, Name FROM Book 

當我們運行由EF生成的絡查詢,SQL Server將引發一個錯誤,你已經達到的最大列數可以在查詢中選擇!

任何幫助非常感謝!


恰好是這種情況,表中有500列,是自參考我們的工具會自動加載心切的第一級關係,這擊中上可以查詢的列數的SQL限制。

我希望我可以設置到相關的實體,例如Id和名稱(其在UI用來查看記錄到用戶)

我想另一種選擇是僅負載有限列控制什麼FK列應該急切加載。但是,對於具有二進制或ntext列的表而言,這仍然存在問題,您可能不希望一直加載該列。

有沒有辦法將多個模型(實體)綁定到Code First中的同一個表上?我們試圖這樣做,我認爲這一努力失敗了。

回答

18

是的,你可以通過使用投影返回列的唯一子集:

var result = from x in context.LargeTable 
      select new { x.Id, x.Name }; 

問題:投影和預先加載不一起工作。一旦你開始使用投影或自定義連接,你正在改變查詢的形狀,並且你不能使用Include(EF會忽略它)。在這種情況下,唯一的辦法就是手動包括在投影結果集的關係:

var result = from x in context.LargeTable 
      select new { 
       Id = x.Id, 
       Name = x.Name, 
       // You can filter or project relations as well 
       RelatedEnitites = x.SomeRelation.Where(...) 
      }; 

您也可以投射到具體的類型,但是特定類型不能映射(所以你不能例如項目LargeTable實體從我的樣品)。對映射實體的投影只能在Linq-to-objects中的物化數據上完成。

編輯:

EF可能存在一些誤解。 EF在實體之上工作 - 實體就是你所映射的。如果您將500列映射到實體,則EF只需按照您定義的那樣使用該實體。這意味着查詢加載實體並堅持保存實體。

爲什麼它以這種方式工作?實體被認爲是原子數據結構,其數據只能被加載和跟蹤一次 - 這是能夠將更改正確保存到數據庫的關鍵功能。這並不意味着如果你需要的話,你不應該只加載列的子集,但你應該明白加載列的子集並沒有定義你的原始實體 - 它被認爲是你實體中數據的任意視圖。這個視圖不會被追蹤,並且無需額外的努力就不會被保存回數據庫(因爲EF沒有關於投影的起源的任何信息)。

EF也放在一些能力的附加約束映射中的每個表都可以正常映射僅一旦實體

  • 。爲什麼?同樣,因爲多次將映射表映射到不同實體可能會破壞正確保存這些實體的能力 - 例如,如果任何非鍵列被映射兩次,並且您加載映射到相同記錄的兩個實體的實例,您將在哪些映射值期間使用保存更改?
  • 有兩個例外,允許你映射表中多次
    • 表每一個分層的繼承 - 這是表可以包含在繼承層次結構中定義多個實體類型記錄的映射。映射到層次結構中的基礎實體的列必須由所有實體共享。每個派生實體類型都可以將其自己的列映射到其特定屬性(其他實體類型都將這些列始終爲空)。無法在多個實體之間共享派生屬性的列。還必須有一個名爲discriminator的額外列,告訴EF哪些實體類型存儲在記錄中 - 此列不能映射爲屬性,因爲它已經映射爲類型鑑別器。
    • 表分割 - 這是單表映射限制的直接解決方案。它允許您將表格拆分爲多個實體,並具有一些限制條件:
      • 實體之間必須存在一對一的關係。您有一個用於加載核心數據的中央實體,所有其他實體都可以通過此實體的導航屬性進行訪問。正常加載,延遲加載和顯式加載正常工作。
      • 該關係是真實的1-1所以兩個部分或關係必須始終存在。
      • 實體不得共享任何財產鍵除外 - 這種約束將解決最初的問題,因爲每個修改的屬性是從分解表映射只有一次
      • 每個實體必須有一個映射關鍵屬性
      • 插入需要整個對象要填充圖表因爲其他實體可以包含映射所需的列

LINQ到-SQL還包含標記的列作爲能力延遲裝入但THI s功能目前無法在EF中使用 - 您可以使用vote for that feature

它會導致你的選擇優化

  • 用突起獲得只讀實體
    • 「視圖」你可以做,在Linq查詢,因爲我在這之前的部分顯示回答
    • 您可以創建數據庫視圖,並將其映射爲一個新的「實體」
    • 在EDMX你也可以使用定義查詢或查詢視圖來封裝SQL或ESQL投影在你的映射
  • 使用表拆分
    • EDMX允許您拆分表格許多實體沒有任何問題
    • Code first allows you splitting table很好,但也存在一些問題,當你分解表超過兩個實體(我認爲,這需要每個實體類型具有導航屬性到分割表中的所有其他實體類型 - 這使得它很難使用)。
+0

我希望有更可靠的方式來指定列。在許多情況下,我們的MVC應用程序爲多個模型共享,我們使用動態LINQ來爲不同的表執行相同的查詢。 – sam360 2012-07-17 19:54:46

+0

動態linq也應該能夠指定投影。 EF是用於處理實體的工具 - 實體就是您已經映射的實體=如果您已將500列映射到實體,則您的查詢無投影將始終返回500列+所有已加載關係的列。 – 2012-07-17 20:23:55

+0

是的,情況就是這樣,表格有500列,並且自動引用我們的工具,自動加載第一級關係,這對於可以查詢的列數有SQL限制。 我希望我可以設置爲只加載相關實體的有限列,如Id和Name(用於在UI中查看記錄給用戶) 我想另一個選項是控制哪些列應該急於加載。然而,對於具有二進制或ntext列的表,您可能不希望加載所有聯繫,這仍然存在問題。 – sam360 2012-07-17 20:59:06

0

創建查詢所需的列數的存儲過程,然後從代碼中調用存儲的特效。