2011-02-12 49 views
10

如果模型打到相同的底層數據庫,是否有方法可以組合來自2個不同實體模型的查詢?我有一個使用EF進行數據訪問的框架(EDM 1) 我有一個客戶端應用程序,它使用框架的服務並且還使用EF作爲自己的數據訪問。 EDM2)跨實體數據模型撰寫查詢

有些情況下,我需要編寫查詢並加入跨2個EDM的實體。

有沒有辦法做到這一點,而不從第一個EDM獲取內存中的數據,然後在第二個EDM的實體內存中應用額外的謂詞/連接?

我希望我這闡明正確的方式

編輯 @Ladislav Mrnka: 第EDM是一個可重用的框架數據訪問層。 把EF生成的實體與這個EDM相結合是沒有意義的 那些消費客戶端 它擊敗了API的可重用性,如果我這樣做,我不得不隨身攜帶附加的膨脹 (EF元數據和數據庫每次我想重新部署框架時,客戶端的表)。此外,這也會使設計師在管理模型時變得笨拙。

我目前使用的是什麼你提到序號項目7作爲solutuon和表現糟糕的 由於這樣的事實,我要結束返回比使用 EDM1然後框架需要更多的數據(即實體)基於來自第二EDM中實體的 屬性的值,根據謂詞/條件過濾掉不需要的謂詞/條件。最終結果是巨大的性能下降和不愉快的DBA。

出於這個原因我最終推動檢索實體 在其中我可以訪問兩個電火花使用的表和申請所需 謂詞和對整個查詢運行在一個數據庫中的存儲過程所需的邏輯,而不是以使內存 的數據,然後過濾掉不必要的ones.Downside的是,我不能使用LINQ

項目你提到聽起來很有趣,但是從8這聽起來像我懷疑 你在設計強類型時間,還是你? 你可以上傳你的代碼樣本嗎?我可以試試嗎?

+0

難道你不能在後端執行此操作,或者sql數據庫目錄是否可以通過鏈接服務器或同等服務器查看對方? – CarneyCode 2011-02-13 10:07:00

+0

@ Carnotaurus:這就是我目前正在做的事情。兩個EDM的表格都在同一個數據庫中,因此我使用Sproc來查詢框架表格(EDM1)和客戶端表格(EDM2)。缺點是我不能使用LINQ – 2011-02-13 23:28:57

回答

4

重要編輯

有在兩個ObjectContext類型實現這一目標的支持沒有建立。您的查詢必須始終針對單個ObjectContext執行。

可能是最好的去路:這對我來說自己嘗試一下很有趣。我從非常簡單的想法開始。兩個EDMX文件(與POCO T4生成器一起使用),每個包含一個實體。我從第二個連接字符串獲取元數據描述並將其添加到第一個連接字符串。我直接使用ObjectContextObjectSet。通過這樣做,我能夠從單個ObjectContext實例查詢和修改兩個實體。我也嘗試從這兩個模型創建查詢連接實體,它工作。 只有當兩個EDMX映射到相同的數據庫(相同的數據庫連接字符串)時,這顯然才起作用。

的重要組成部分,是連接字符串:

<configuration> 
    <connectionStrings> 
    <add name="TestEntities" connectionString="metadata=res://*/FirstModel.csdl|res://*/FirstModel.ssdl|res://*/FirstModel.msl|res://*/SecondModel.csdl|res://*/SecondModel.ssdl|res://*/SecondModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.;Initial Catalog=Test;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" /> 
    </connectionStrings> 
</configuration> 

此連接字符串包含兩種模式元數據 - FirstModel.edmx和SecondModel.edmx。

的另一個問題是強迫EF使用來自這兩個文件的映射。每個EDMX文件必須爲SSDL和CSDL定義唯一的容器。 ObjectContext提供稱爲DefaultContainerName的財產。該屬性可以直接設置或通過一些構造函數重載。一旦你設置了這個屬性,你可以將你的ObjectContext實例綁定到單個EDMX上 - 對於這個場景,你不能設置這個屬性。省略DefaultContainerName可能會產生一些後果,因爲某些功能和聲明可能會停止工作(您將收到運行時錯誤)。除非您想使用某些高級功能,否則您應該沒有POCO問題。如果你使用的是實體對象(重EF實體,你極有可能不得不proplems使用被定義爲字符串的實體集的所有方法都依賴於容器由於此我建議使用只在必要時這樣的配置 - 交叉車型查詢

最後的問題就是產生實體和「強類型」衍生ObjectContext去的方式是修改T4模板,這樣一個模板從多個EDMX文件個個讀取數據,並生成語境最終實體 - 我已經在我的項目這樣做的,它的工作原理默認的T4實現並不遵循前面段落中描述的需要的方法從默認的T4實現派生的ObjectContext取決於單個EDMX和實體容器


這部分是在上次編輯之前編寫的。

我離開的信息,其他人只是因爲他們中的一些可以在其他情況下,包括與多個數據庫的工作是有用的。

ORM等實體框架上對象世界和數據庫世界之間的映射的頂部操作。在EF中,對象世界由CSDL描述,數據庫世界被描述爲SSDL,並且它們之間的映射被描述爲MSL(全部僅僅是具有衆所周知的模式的XML)。在設計時這些描述是存儲在EDMX文件中的模型的一部分。在編譯過程中,這些描述是從EDMX中提取的,並且默認作爲資源文件包含在已編譯的程序集中。

當您創建的實例ObjectContext它接收的連接字符串包含參照CSDL,SSDL和MSL資源文件。 SSDL或MSL不指定include元素來添加來自其他文件的信息。 CSDL提供Using元素,這將允許您重新使用現有映射,但此功能不受設計人員支持。 ConnectionString用於初始化EntityConnection實例,該實例又用於初始化ObjectContext的MetadataWorkspace(運行時映射信息)。 ObjectContext也不提供將多個上下文嵌套到hiearchy中的任何功能。 連接字符串不能包含對這些文件的多個實例的引用。 編輯:它可以。我只是測試它。看到最初的段落。

當你的ObjectContext的實例中運行的LINQ或ESQL查詢它usese MSL映射你的實體或POCO類(由CSDL定義)到數據庫查詢(通過數據庫表的SSDL描述定義)。如果它沒有這些信息,它將不起作用(並且如果它存儲在單獨的EDMX中,則不能獲得該信息)。

那麼如何解決這個問題呢?有幾種方法:

  1. 始終考慮:合併你的映射成一個文件(如果有多個文件被用於同一個數據庫)。這應該是使用EF的方式,正如您所提到的,您正在查詢相同的數據庫,因此不需要兩個EF模型。
  2. 第二個模型中的重複實體描述。如果您使用EF4和POCO,則可以將來自多個模型的相同描述映射到一個POCO類定義中。我不喜歡這個解決方案,但有時它可以提供幫助。
  3. 定義包含查詢(或查詢的核心)的數據庫視圖或存儲過程,並將其映射到一個模型中以形成新實體。
  4. 在一個模型中使用DefiningQuery(如果使用從數據庫更新功能,您可能需要第三個)並將其映射到新實體。 DefiningQuery是在SSDL中定義的自定義SQL查詢,而不是表或視圖描述。
  5. 使用Function以及指定數據庫查詢的自定義CommandText。這與使用DefiningQuery類似,並且具有相同的限制。您必須手動(在EDMX中)將函數的結果映射到新的複雜類型(與映射到新實體的DefiningQuery的另一個區別)。
  6. 定義查詢結果的新類型(類型的屬性必須與查詢中返回的列名稱相同)並使用ObjectContext的ExecuteStoreQuery(僅在EF4中)。
  7. 將查詢分爲兩部分,每部分分別在自己的上下文中執行,並使用linq-to-objects獲取結果。我不喜歡這個解決方案。

  8. 這一個只是高層次的想法 - 我沒有嘗試它,我不知道它是否有效。如上所述,運行時間映射取決於從EntityConnection填充的MetadataWorkspace實例的內容。 EntityConnection也提供了直接接收MetadataWorkspace實例的構造函數。所以一般情況下,如果可以從多個EDMX中填充MetadataWorkspace,則不需要多個ObjectContext實例,但是您的映射仍將分爲兩個EDMX。這將有希望允許您在兩個映射文件上編寫自定義Linq查詢)。 編輯:它應該是可能的,因爲如果您在連接字符串中定義多個映射,EF正是如此。

  9. 使用CSDL Using feature將模型分解爲多個重用部分。