2014-09-02 45 views
5

我們有一個龐大的數據庫,有770個表,並希望用EF 6.1x做一些性能測試。實體框架6只包含所有表的一個子集的DBContext

我們只想查詢那770個表中的5個。是否有可能創建一個只有5-6個實體/ DBSets的「輕量級」DBContext,而不是使用完整的770-tables-context?

當我們使用完整的上下文時,帶有4個連接的簡單查詢需要45秒。那44秒太長了。 我們使用代碼優先(反向工程)。

問題: 當我們創建完整的上下文的這樣的「光」的版本(即只有5桌),EF抱怨說,所有在某種程度上涉及到這5個表中的其他實體有丟失的鑰匙。我們只映射這5張表的關鍵字,屬性和關係,但其他關鍵字則不會。

由於用LINQ寫的查詢只查詢5個表,EF應該忽略其他765個表,但它不會。 爲什麼不呢? LazyLoading = true/false似乎對此沒有任何影響。

注意:很明顯,人們可以在數據庫中創建一個視圖,用來處理LINQ查詢的代碼。問題是可以用上面的「輕量級」DbContext來完成。

有「光」版本上下文:

public class ItemLookupContext : DbContext 
{ 
    static ItemLookupContext() 
    { 
     Database.SetInitializer<ItemLookupContext>(null); 
    } 

    public ItemLookupContext() 
     : base("Name=ItemLookupContext") 
    { 
     //Configuration.LazyLoadingEnabled = true; 
    } 

    public DbSet<Identity> Identities { get; set; } 
    public DbSet<Item> Items { get; set; } 
    public DbSet<Price> Prices { get; set; } 
    public DbSet<Department> Departments { get; set; } 
    public DbSet<Brand> Brands { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add(new IdentityMap()); 
     modelBuilder.Configurations.Add(new ItemMap()); 
     modelBuilder.Configurations.Add(new PriceMap()); 
     modelBuilder.Configurations.Add(new DepartmentMap()); 
     modelBuilder.Configurations.Add(new BrandMap()); 

     //ignore certain entitities to speed up loading? 
     //does not work 
     modelBuilder.Ignore<...>(); 
     modelBuilder.Ignore<...>(); 
     modelBuilder.Ignore<...>(); 
     modelBuilder.Ignore<...>(); 
     modelBuilder.Ignore<...>(); 
    } 
} 
+1

這當然是可能的,實際上建議。在較大的數據庫環境中,對於表的子集有多個不同的上下文通常會提高性能。 – DavidG 2014-09-02 09:39:04

+0

一些代碼將有助於理解您的問題,但我猜你會尋找類似http://stackoverflow.com/questions/17246069/multiple-dbcontexts-on-one-db-with-code-first-migrations? – fuchs777 2014-09-02 09:43:28

+0

是簡單查詢的第一個exe,那是觸發上下文構建的一個查詢? – tschmit007 2014-09-02 09:57:51

回答

2

當你有A類和B類之間的多到一的關係:

public class A 
{ 
    public B b {get; set;} 
} 
public class B 
{ 
    public ICollection<A> As {get; set;} 
} 

,並確定以下DbContext ,EF 自動包括DbSet<B>DbContext

public class MyContext : DbContext 
{ 
    ... 
    public DbSet<A> As { get; set; } 
} 

所以,如果你想你的光DbContext不包括相關DbSet S,只需使用Ignore方法:

public class MyContext : DbContext 
{ 
    ... 
    public DbSet<A> As { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Ignore<B>(); 
    } 
} 
+0

謝謝!它可以通過其他方式來完成嗎?在需要時調用Include()並讓EF默認忽略所有DBSets,而不是包含它們? – John 2014-09-02 10:28:45

+0

@John,如果你'忽略'一個類,你不能用'Include()'來使用它。 – Masoud 2014-09-02 10:31:31

+0

我的意思是這樣的:如果一個表有45個引用其他DBSets,我必須調用Ignore()45次,還是有更簡單的方法來排除大量的相關集? – John 2014-09-02 10:40:13

0

它看起來像你一樣使用實體框架電動工具的工具來生成實體類和映射。這將爲數據庫中的每個表生成一個類,一個巨大的上下文,所有這些類的映射以及所有可能的關聯。這太過分了。

首先刪除您不需要的所有類和映射。然後刪除所有關聯以刪除已離開的幾個類中的類,而不是原始外鍵字段。除了您需要的幾個外,還從上下文中刪除所有DbSets。

這個瘦身的類模型本身是一致的。它不會關聯數據庫中的所有實體,但可以通過引用上下文之外的實體的外鍵值進行過濾。

如果您以任何其他方式生成/創建代碼,這仍然是關鍵:只對類模型中的其他類使用導航屬性。對於其他引用使用原始外鍵屬性。

+0

我擔心有人會建議。我確實使用過電源工具,但是我從幾個生成的實體創建的dbcontext只是我們需要的許多dbcontext中的一個。從你寫的內容來看,我認爲不可能在多個上下文中使用相同的實體類。但是,那麼我需要爲每個dbcontext反覆創建相同的實體類嗎?那麼Item1.cs爲dbcontext A,Item2.cs爲dbcontext B等? – John 2014-09-03 10:22:58

+0

是的,基本上是這樣。但是我認爲你應該嘗試創建更大的上下文,這些上下文覆蓋了數據庫合理的不同集合,並且服務於多個任務區域。因此,您可以減少重疊類的數量。 [EntityFramework Reverse POCO Code First Generator](https://efreversepoco.codeplex.com/documentation)在這裏可能會有所幫助。 – 2014-09-03 11:25:33

+0

只要您爲每個導航屬性創建一個單獨的'EntityTypeConfiguration <...>'映射,它具有'Ignore();'''''''''''''''''''映射。 – sliderhouserules 2016-03-30 23:46:15

2

只是簡單地創建你的DbContext爲您的表。爲了防止實體框架呻吟未映射的表,你已經在你的應用程序中關閉了數據庫初始化。把這個在您的Global.asax/Startup.cs

Database.SetInitializer<YourDbContext>(null); 

它告訴EF停止對你的DbContext比較實際的數據庫結構。 這也意味着如果有人改變你的EF映射表,你沒有機會得到有關的通知。