2

我想在運行時從的DbContext獲取數據庫表名獲取表名,我發現posts談論它是不是EF 4.x中可能得到SSpace項目(以及表名)默認情況下,這些操作還沒有公共的API。如何從的DbContext在運行時

但我試圖使這方面的一些測試,我能夠從的DbContext在運行時使用調試器

這句法由Visual Studio生成

((System.Data.Entity.DbContext)(context)).System.Data.Entity.Infrastructure.IObjectContextAdapter.ObjectContext.MetadataWorkspace._itemsSSpace 

我拿到表名進行了一些修改,以使其可用於代碼,並且產生至此

var objContext = (context as IObjectContextAdapter).ObjectContext; 
var metaData = objContext.MetadataWorkspace; 
var items = metaData.GetItems(DataSpace.SSpace); 

雖然它遵循相同目標,items拋出異常The space 'SSpace' has no associated collection.

  • 第一:爲什麼會出現此錯誤。
  • 第二:有沒有什麼辦法可以得到這個SSpcae的物品,或者表名?
+0

可能重複[從實體框架元數據數據庫表名(http://stackoverflow.com/questions/1895455/獲取數據庫表名,從實體框架元數據) – bummi

回答

2

您會得到該錯誤,因爲只有在您執行某項操作(執行查詢)才能使EF需要存儲集合時,存儲集合纔會被填充。但即使你擁有它,它也會對你沒有好處。您可以通過這種方式獲取表名稱列表,但與實體的映射位於CSSpace項目集合中,因爲它使用EF運行時內部的類型,所以完全無法訪問。如果您有實體A和B以及表C和D,即使您知道您有直接的一對一映射,也無法找到A是映射到C還是映射到D.

4

這是一種方法在運行時。

 public static List<string> GetTableNames() 
    { 
     List<string> tableNameList = new List<string>(); 
     // use DBContext to get ObjectContext 
     DatabaseContext db = new DatabaseContext(); 
     IObjectContextAdapter adapter = db as IObjectContextAdapter; 
     System.Data.Objects.ObjectContext objectContext = adapter.ObjectContext; 

     ReadOnlyCollection<EntityType> allTypes = objectContext.MetadataWorkspace.GetItems<EntityType>(DataSpace.CSpace); 
     foreach (EntityType item in allTypes) 
     { 
      // Create full assembly name 
      string typeName = "original.poco.namespace." + item.Name; 
      Type type = Type.GetType(typeName); 

      // wrap into a function 
      string sql = db.Set(type).ToString(); 
      Regex regex = new Regex(@"FROM \[dbo\]\.\[(?<table>.*)\] AS"); 
      Match match = regex.Match(sql); 
      tableNameList.Add(match.Groups["table"].Value); 
     } 

     return tableNameList; 
    } 
1

我在各地都在使用這些類;應該證明有幫助。與EF4或5一起工作。要使ObjectContext從DbContext傳遞到頂層EntityNavigationList.List,請使用(((IObjectContextAdapter)myDbContext).ObjectContext。表名的簡單列表將是EntityNavigationList.List中每個項目的FromEntity。

public class NavigationItem 
{ 
    public string FromEntity { get; set; } 
    public string ToEntity { get; set; } 
    public RelationshipMultiplicity FromMultiplicity { get; set; } 
    public RelationshipMultiplicity ToMultiplicity { get; set; } 
    public string ForeignKeyColumn { get; set; } 
    public string PrimaryKeyColumn { get; set; } 
    public EntitySetBase EntitySet { get; set; } 

    /// <summary> 
    /// Entity type may be "Formula"; entity set may be "Formulae" 
    /// </summary> 
    public string EntitySetName { get { return EntitySet == null ? string.Empty : EntitySet.Name; } } 
} 

public static class EntityNavigationList 
{ 
    private static List<NavigationItem> _navItems; 

    public static List<NavigationItem> List(ObjectContext context) 
    { 
     if (_navItems == null) 
     { 
      InitializeNavigationItems(context); 
     } 
     return _navItems; 
    } 

    /// <summary> 
    /// Create a list of all navigation items in the model 
    /// </summary> 
    private static void InitializeNavigationItems(ObjectContext context) 
    { 
     var entityMetadata = context.MetadataWorkspace.GetItems(DataSpace.CSpace); 
     var entitySetMetadata = context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace).BaseEntitySets; 

     var query = from meta in entityMetadata 
         .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType) 
        from p in (meta as EntityType).NavigationProperties 
        let foreignKey = (p.ToEndMember.DeclaringType as AssociationType).ReferentialConstraints.FirstOrDefault() 
        let primaryKey = (meta as EntityType).KeyMembers 
        select new NavigationItem 
        { 
         FromEntity = p.FromEndMember.Name, 
         ToEntity = p.ToEndMember.Name, 
         FromMultiplicity = p.FromEndMember.RelationshipMultiplicity, 
         ToMultiplicity = p.ToEndMember.RelationshipMultiplicity, 
         ForeignKeyColumn = foreignKey == null ? string.Empty : foreignKey.ToProperties.First().ToString(), 
         PrimaryKeyColumn = primaryKey == null ? string.Empty : primaryKey.First().Name, 
         /// We need the corresponding entity set so we can get it's name (formula belongs to entity set "formulae") 
         EntitySet = (from moMeta in entitySetMetadata 
             where moMeta.ElementType.Name == p.FromEndMember.Name 
             select moMeta).FirstOrDefault() 
        }; 

     _navItems = query.ToList(); 
    } 

} 
1

這是今天制定了來自微軟的Northwind示例數據庫,演示如何從實體數據模型獲取表的列表,然後從一個DataGridView選擇的表顯示前x行一些代碼。

要運行下面的代碼是:

  1. 創建一個Windows窗體應用程序
  2. 添加實體數據模型爲Northwind數據庫,稱之爲「NorthwindModel」
  3. 添加兩個組合框和一個datagridview的(tablesComboBox,topXComboBox和dataGridViewForOutput)
  4. 項目添加到topXComboBox(全部,前5,前10名等(必須是多重的5碼工作)
  5. 變化形式名字的MainForm
  6. 突出顯示所有代碼的形式文件,並替換爲以下


    using System; 
    using System.Data.Entity; 
    using System.Linq; 
    using System.Reflection; 
    using System.Windows.Forms; 

    namespace EntityFrameworkBrowser 
    { 
     public partial class mainForm : Form 
     { 

      public mainForm() 
      { 
       InitializeComponent(); 
      } 

      private void mainForm_Load(object sender, EventArgs e) 
      { 
       Type type = typeof(NorthwindModelEntities); 
       var query = type.GetProperties().Where(p => p.GetMethod.ToString().ToLower().Contains(".dbset")).Select(m => m.Name); 
       tablesComboBox.DataSource = query.ToList(); 
       topXComboBox.SelectedIndex = 1; 
      } 

      private async void BindTableData() 
      { 
       // Ensure the form has been initialised 
       if (topXComboBox.SelectedIndex.Equals(-1)) 
       { 
        return; 
       } 
       // Get the DB context 
       NorthwindModelEntities dbContext = new NorthwindModelEntities(); 
       // Get a reference to the type of the model 
       Type type = typeof(NorthwindModelEntities); 
       // Get the table name selected by the user in the combo box 
       string tableName = tablesComboBox.SelectedItem.ToString(); 
       // Get a reference to the DbSet from the model 
       var prop = type.GetProperty(tableName); 
       // Get a reference to the getter for the DbSet 
       MethodInfo get = prop.GetMethod; 
       // Invoke the getter for the DbSet 
       object tableContent = get.Invoke(dbContext, null); 
       // Create a query that will return all records from the selected table 
       IQueryable query = (IQueryable)tableContent; 
       // Find out how many records the user has requested, All, Top5, Top 10, etc 
       int count = topXComboBox.SelectedIndex * 5; 
       // If a value other than all (selected index 0) has been selected the query needs to be refactored 
       if (count != 0) 
       { 
        // Get the element type for the DbSet from the entity data model 
        Type returnType = query.ElementType; 
        // Get a reference to the 'Take' extension method 
        MethodInfo takeMethod = (MethodInfo)typeof(Queryable).GetMethod("Take"); 
        // Make a generic version of the 'Take' method 
        MethodInfo m = takeMethod.MakeGenericMethod(returnType); 
        // Refactor the query to take the top X records based on the user combo box selection 
        query = (IQueryable)m.Invoke(null, new object[] { query, count }); 
       } 
       // Execute the query and bind the results to the data grid view 
       dataGridViewForOutput.DataSource = await query.ToListAsync(); 
      } 

      private void tablesComboBox_SelectedIndexChanged(object sender, EventArgs e) 
      { 
       BindTableData(); 
      } 

      private void topXComboBox_SelectedIndexChanged(object sender, EventArgs e) 
      { 
       BindTableData(); 
      } 
     } 
    } 

希望這些意見應該解釋正在發生的事情,你不會猜。

希望它可以幫助別人,因爲它採取了一些工作了

:0)