2013-02-07 30 views
2

我目前工作的一個EF流利的項目,該項目正在與表每類型的架構模型第一種方法的(是的,我不喜歡這樣寫它) EF 4.3。實體框架流利,表,每型性能的替代品

正如我已經發現了,在過去的幾個月裏,表每類型和繼承只是沒有發揮好 - >more information。我使用一個具有七個派生類的單個基類,並且只是在七個派生類中返回項目並不是特別快。在執行時間方面,爲了檢索5條記錄清單,EF記錄的時間爲5到7秒,隨後的執行時間約爲2.5到4秒。可以肯定地說,這是不可接受的,所以我正在尋找替代方法...

我可以做的是多次命中數據庫,即嘗試檢索每個類型的對象個別並整理成一個集合;然而,該代碼充其量是強大的,即

IList<MyBaseClass> items = new List<MyBaseClass>(); 

dbContext.Database.SqlQuery<MyFirstDerivedClass>("SELECT * FROM MyBaseClass INNER JOIN MyFirstDerivedClass ON...").ToList().ForEach(x => items.Add(x)); 

... repeat for each derived class... 

return items; 

但它的工作!數據庫中的第一個命中需要2秒,隨後的查詢僅需200毫秒。

我的問題是,這不是非常優雅,可維護等等,我一直在推動與dbContext投入到一個ObjectContext和像這樣的存儲過程('spGetMyDerivedItems')返回所有的得到的結果集排序中一個數據塊的命中...

IList<MyBaseClass> items = new List<MyBaseClass>(); 

ObjectContext oContext = ((IObjectContextAdapter)dbContext).ObjectContext; 

using (var connection = oContext.Connection as EntityConnection) 
{ 
    EntityCommand command = connection.CreateCommand(); 
    command.CommandType = CommandType.StoredProcedure; 
    command.CommandText = "spGetMyDerivedItems"; 
    connection.Open(); 

    using (EntityDataReader reader = command.ExecuteReader()) 
    { 
     oContext.Translate<MyFirstDerivedClass>(reader).ToList().ForEach(x => items.Add(x)); 
     reader.NextResult(); 
     ...repeat for each derived type...   
    } 
} 

return items; 

然而,這不符合一個InvalidOperationException異常抱怨的CommandText是無效的,而我必須提供一個「容器名稱」工作。我的猜測是,如果我使用的是EDMX文件,我可以設置這個設置項目(並且使用DefaultContainerName不起作用)。但我正在採取一種流暢的方法,我覺得我已經陷入死衚衕。

所以......

什麼樣的方法都可以解決的table-per-型EF的性能問題和? 是否可以使用Fluent/Model First方法通過ObjectContext執行存儲過程? 我可以執行標準的SQLClient.SqlDataReader並轉換成ObjectContext嗎?

在此先感謝...

+0

它可能不是你要找的答案,所以我只留下評論和一些參考這裏:在EF 10/.NET 4.5 TPT的表現已經「顯著改善」,根據聲明這裏:HTTP:/ /data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/1015337-tpt-table-per-type-in​​heritance-performance在另一方面,EF隊依然鼓勵使用TPT的位置:HTTP ://msdn.microsoft.com/en-us/data/hh949853.aspx我不知道什麼改進意味着秒或毫秒。 – Slauma

+1

通常,SQL生成質量和性能(特別是由於EF 5/.NET 4.5中的編譯查詢的默認使用)得到了改進:http://blogs.msdn。com/b/adonet/archive/2012/02/14/sneak-preview-entity-framework-5-0-performance-improvements.aspx and http://www.outofmemory.co.uk/entity-framework-5-顯着更快的網絡4-5 /改進的TPT可能會受益於兩者。 – Slauma

+0

出於好奇,爲什麼不使用table-per-inheritance? –

回答

1

確定 - 它看來,ObjectContext的可以從System.Data.SqlClient.SqlDataReader意味着我不需要推導(直接)從翻譯的DbContext。這裏的示例代碼...

IList<MyBaseClass> items = new List<MyBaseClass>(); 

ObjectContext oContext = ((IObjectContextAdapter)dbContext).ObjectContext; 

using (var sqlConn = new SqlConnection(dbContext.Database.Connection.ConnectionString)) 
{ 
    SqlCommand sqlComm = new SqlCommand(){ 
     Connection = sqlConn, 
     CommandText = "spGetMyDerivedItems", 
     CommandType = CommandType.StoredProcedure 
    }; 
    sqlConn.Open(); 

    using (SqlDataReader reader = command.ExecuteReader()) 
    { 
     oContext.Translate<MyFirstDerivedClass>(reader).ToList().ForEach(x => items.Add(x)); 
     reader.NextResult(); 
     ...repeat for each derived type...   
    } 
} 

return items; 

很明顯,最好的答案是英孚會選擇這個,但我很滿意上述的時刻。移動到EF5聽起來像一個很好的舉措 - 但不同時間尺度的更好的魔鬼,你知道:)

感謝您的幫助。