2012-01-03 24 views
1

我的項目中有一個要求,在運行時動態添加/刪除字段。我已經創建了這個功能,但不是在EF中。我想使用EF創建此功能。任何想法如何做到這一點?如何在運行時使用Entity Framework動態添加/刪除字段?

+0

EF不適合這種類型的要求。 – Eranga 2012-01-03 10:09:58

+0

'field'是什麼意思?你的意思是你想添加數據庫列而不必重新編譯你的項目? – Steven 2012-01-03 10:17:24

+0

@ Steven - 是的,是否有可能在運行時重新編譯模式的方法? – user335160 2012-01-03 10:21:14

回答

1

在運行期間添加和刪除字段並不是一個好主意。
數據庫結構應該是靜態的,因爲它應該反映您的類結構,並且您的類結構是靜態的,無論您是否需要它。

如果你有一個動態表,你最好實施它,例如,有一個表「rowID,field,value」的字段,並用這種方式填寫值。

如果您確實需要在運行時向表中添加/刪除字段,則可以創建一個存儲過程來添加/刪除該字段,然後將SP與實體框架進行映射。
但是,這可能會導致很多問題,因爲實體框架將無法映射/取消映射新的/已刪除的字段,因此在嘗試訪問該表時會崩潰。

+0

@ Svarog-是的,我經歷過這一次,這就是爲什麼我用另一種方法。我想我的運氣她在計算器中,如果有人之前做過。我不知道這個鏈接http://efmodeladapter.codeplex.com適用於我的問題。 – user335160 2012-01-03 10:24:08

+0

運行時模型適配器用於添加/刪除前綴和這種微調。你不能用它改變你的類/表中的字段。 – Svarog 2012-01-03 10:51:53

+0

@ Svarog好的,謝謝澄清。 – user335160 2012-01-03 10:59:55

3

如果您需要動態數據結構,則必須使用完全不同的體系結構,否則無法使用EF。 EF不是動態更改數據庫的工具 - 只要看看如何使用EF。您將靜態表映射到靜態類定義。如果您在運行時更改表,您如何更改類(EF中不支持dynamic)?

作爲替代數據庫結構的示例,您可以使用具有多個不同類型的預定義列的數據庫,並且新字段將映射到新類型。您將在應用程序中添加額外的「映射」層,它將根據存儲在別處的某些類型元數據來解釋您的數據庫內容。例如,Sharepoint(至少2007年)使用了這種方法,您已經單獨存儲了內容類型(數據描述),但所有內容都位於一個包含大量列的巨大表格中。

另一個例子是結構,其中核心數據(在所有實體之間共享)的單獨表,用於屬性描述的單獨表以及與核心數據相關的屬性值的單獨表。這個數據庫結構有一個名字,但我現在不記得它。

每個動態方法都有它的價格。一般來說,你會失去一些強類型工作的一部分,你會失去表現。

您的鏈接工具不適用於更改數據庫結構。它僅用於修改映射中的名稱,但表結構必須保持不變。

+0

@ Ladislav - 一旦db中有任何更改,是否沒有辦法在運行時重新編譯模式(edmx)? – user335160 2012-01-03 11:04:51

+1

「重新編譯」模型是不夠的,您需要重新編譯代碼並重新加載程序集,而且這非常困難,因爲例如一旦您加載程序集,就無法卸載它 - 只能卸載加載它的AppDomain。 – 2012-01-03 11:38:57

+0

任何人都知道數據庫結構的名稱?它是「重要價值商店」嗎? – AXMIM 2017-07-12 21:07:42

1

這是來自Rowan Miller博客的takne verbatin。

http://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/

仍必須進行更改,以便從某些配置源或數據庫表中的字段中讀取類的屬性。


動態生成模型的代碼第一次 發表於3月26日,2012年

我最近回答了幾個電子郵件關於這一主題,因此覺得時間把它變成一個博客帖子。

在這種情況下,構成模型的類集在編譯時是未知的,並且在運行時被動態地發現。這種情況的一個例子是WordPress/Orchard /等。它允許插入模塊。這些模塊位於單獨的程序集中,可能包含表示要在應用程序數據庫中保留的數據的類。這些類都被拉入用於數據訪問的中央Code First模型。

尋找類 有很多不同的方法來確定要包含在模型中的類。在這個例子中可以使用[持久]屬性,像這樣:

[AttributeUsage(AttributeTargets.Class) 公共類PersistentAttribute:屬性 {} 現在 我們可以添加一些邏輯的OnModelCreating我們的方法上下文來掃描程序集並使用[Persist]屬性添加任何類。我們假設可能包含類的程序集全部加載到當前的AppDomain中,當然你可能有一些其他機制提供了要檢查的程序集列表。

public class MyContext : DbContext 
{ 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
    var entityMethod = typeof(DbModelBuilder).GetMethod("Entity"); 

    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) 
    { 
     var entityTypes = assembly 
     .GetTypes() 
     .Where(t => 
      t.GetCustomAttributes(typeof(PersistentAttribute), inherit: true) 
      .Any()); 

     foreach (var type in entityTypes) 
     { 
     entityMethod.MakeGenericMethod(type) 
      .Invoke(modelBuilder, new object[] { }); 
     } 
    } 
    } 
} 

在這個例子中,整個模型是動態發現的,但你也可以有與模型構建器也註冊了模型的一些靜態部分。

使用EntityConfiguration的替代 Code First允許您創建一個派生自EntityTypeConfiguration的類來封裝實體的Fluent API配置。如果您使用這種方法進行配置,您可以查找這些配置類並註冊它們,而不是查找要註冊的實體。請注意,我們正在過濾出EntityFramework程序集,因爲它有一些內部使用的配置類。

public class MyContext : DbContext 
{ 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
    var addMethod = typeof(ConfigurationRegistrar) 
     .GetMethods() 
     .Single(m => 
     m.Name == "Add" 
     && m.GetGenericArguments().Any(a => a.Name == "TEntityType")); 

    foreach (var assembly in AppDomain.CurrentDomain 
     .GetAssemblies() 
     .Where(a => a.GetName().Name != "EntityFramework")) 
    { 
     var configTypes = assembly 
     .GetTypes() 
     .Where(t => t.BaseType != null 
      && t.BaseType.IsGenericType 
      && t.BaseType.GetGenericTypeDefinition() ==  typeof(EntityTypeConfiguration<>)); 

     foreach (var type in configTypes) 
     { 
     var entityType = type.BaseType.GetGenericArguments().Single(); 

     var entityConfig = assembly.CreateInstance(type.FullName); 
     addMethod.MakeGenericMethod(entityType) 
      .Invoke(modelBuilder.Configurations, new object[] { entityConfig  }); 
     } 
    } 
    } 
} 

如果模型更改會怎樣? Code First遷移到救援......您可能無法使用Package Manager控制檯中的遷移,因爲發現您的模型的邏輯可能需要完整的應用程序才能運行。幸運的是,這些命令僅僅是一個API的精簡包裝。這裏有一些代碼可以在新的類或屬性添加到模型中時自動更改數據庫。我最近的博客文章有更多關於從代碼中調用Migrations的細節。

var config = new DbMigrationsConfiguration<MyContext> {  AutomaticMigrationsEnabled = true }; 
var migrator = new DbMigrator(config); 
migrator.Update(); 
相關問題