2010-10-08 2 views
17

Вот и все. Это довольно просто. У меня есть edmx и вы хотите динамически запрашивать его для таблиц и (надеюсь) динамически строить против этой таблицы. Это возможно?Entity Framework - Получить список таблиц

=========

UPDATE:

Я включил все таблицы БД, но никаких взглядов или SP, в самом контексте. У нас есть много таблиц, которые вводят информацию (с идентификаторами). Так, например, цвета, тип файла или тип протокола. Я хочу иметь возможность взять запрос типа (файла) для таблиц, которые могут содержать информацию о типе (File, FileType) и возвращать его с идентификатором.

Итак, я могу найти ... Бизнес-блок (или цвет или файл), и код исчезнет и будет искать контекст для BusinessUnit (или цвета или файла) и BusinessUnitType (или ColorType или FileType). Если он найдет один из них, он запросит его и вернет все строки, чтобы я мог видеть, содержит ли это информацию о типе (позже я уточню его, чтобы возвращать только идентификаторы и описания, аббревиатуру или поля имени, а также ограничивающие строки и т. Д.). и иметь возможность найти связанный идентификатор для конкретного.

+2

таблиц или сущностей? Аннотация или конкретный? Имена или типы? Зачем? Пожалуйста, будьте конкретны. –

+0

Столы - все. Просто таблицы. То, что вы получите, запросив sysobjects в SQL Server. – Michael

+0

Вам нужны таблицы в вашем контексте или в БД? – Nix

ответ

13

Для первого вопроса о том, как перечислять таблицы в базе данных, этот код получит их для вас, конечно, те, которые были импортированы в ваш EDM, что обязательно не все таблицы в вашем хранилище данных.

var tableNames = context.MetadataWorkspace.GetItems(DataSpace.SSpace) 
         .Select(t => t.Name) 
         .ToList(); 

Этот код вызовет InvalidOperationException с этим сообщением:
Пространство 'SSpace' не имеет связанного Collection
И это потому, что в отличие от CSpace, SSpace (SSDL) не загружается до тех пор, пока необходимо. и попытка прочитать их с помощью MetadataWorkspace не считается необходимой. Это необходимо во время компиляции запроса, а затем при материализации объекта. Чтобы обмануть MetadataWorkspace, чтобы загрузить его для нас, нам нужно запустить такой запрос, как показано ниже, прежде чем запускать основной запрос, который дает нам имена таблиц.

string temp = ((ObjectQuery)context.[EntitySetName]).ToTraceString(); 

Вы можете прочитать здесь: Quick Trick for forcing MetadataWorkspace ItemCollections to load

Однако, если ваше намерение состоит в том, чтобы построить динамический запрос к вашим таблицам типа, то вам не нужно возиться с SSpace, вы должны получить его из CSpace (концептуальная модель).Ниже приведен пример кода, о том, как построить динамический запрос с наличием только часть имени таблицы:

ObjectResult<DbDataRecord> GetAllTypes(string name) { 
    using (TypeEntities context = new TypeEntities()) { 

    MetadataWorkspace metadataWorkspace = context.MetadataWorkspace; 
    EntityContainer container = metadataWorkspace.GetItems<EntityContainer> 
                 (DataSpace.CSpace).First(); 
    string namespaceName = metadataWorkspace.GetItems<EntityType> 
             (DataSpace.CSpace).First().NamespaceName; 

    string setName = string.Empty; 
    string entityName = name + "Type"; 

    EntitySetBase entitySetBase = container.BaseEntitySets 
      .FirstOrDefault(set => set.ElementType.Name == entityName); 

    if (entitySetBase != null) { 
     setName = entitySetBase.Name; 
    } 
    EntityType entityType = metadataWorkspace 
     .GetItem<EntityType>(namespaceName + "." + entityName, DataSpace.CSpace); 

    StringBuilder stringBuilder = new StringBuilder().Append("SELECT entity "); 
    stringBuilder 
     .Append(" FROM " + container.Name.Trim() + "." + setName + " AS entity "); 
    string eSQL = stringBuilder.ToString(); 

    ObjectQuery<DbDataRecord> query = context.CreateQuery(eSQL); 
    ObjectResult<DbDataRecord> results = query.Execute(MergeOption.AppendOnly); 
    return results; 
    } 
} 


код Пояснение: Мое предположение, что ваши имена таблиц типа оканчиваются в «Тип» как postfix (например, ColorType), поэтому вы можете вызвать GetAllType («Цвет») и искать в вашей модели ColorType EntityObject и предоставить вам все возможные значения. Код может выглядеть страшно, но это довольно простой материал. В основном все, что он делает, это то, что он получает всю необходимую информацию из MetaData (например, имя EntitySet, имя пространства имен и т. Д.) На основе параметра метода, а затем создает запрос EntitySQL «на лету», затем выполняет его и возвращает Результаты.

+2

Какая версия EF вышеуказанного кода, пожалуйста? Я пытался в EF4.0, и «t => t.Name» даже не компилируется. Любые решения? –

+0

Я использую EF 6.1.1, и этот код работал для меня Список tableList = db.MetadataWorkspace.GetItems (DataSpace.CSpace). Выбрать (x => x.Name); –

+0

У меня такая же проблема @LeiYang исправлена ​​с: var items = objectContext.MetadataWorkspace.GetItems (DataSpace.SSpace); – Evilripper

2

На всякий случай это помогает, я вытащил их из одного из классов ObjectContextExtension.

Вы можете запросить контекст объекта и получить имена, как показано ниже. Не стесняйтесь изменять это, как хотите.

public static class ObjectContextExtensions 
{ 
    public static string GetEntitySetName<T>(this ObjectContext theContext, T eo) where T : EntityObject 
    { 
     string entitySetName = ""; 
     if (eo.EntityKey != null) 
     { 
      entitySetName = eo.EntityKey.EntitySetName; 
     } 
     else 
     { 
      string className = typeof(T).Name; 
      var container = 
        theContext.MetadataWorkspace.GetEntityContainer(theContext.DefaultContainerName, DataSpace.CSpace); 
      entitySetName = (from meta in container.BaseEntitySets 
          where meta.ElementType.Name == className 
          select meta.Name 
          ).First(); 

     } 

     return entitySetName; 
    } 
    public static IEnumerable<EntitySetBase> GetEntitySets(this ObjectContext theContext) 
    { 
      var container = 
        theContext.MetadataWorkspace 
         .GetEntityContainer(
          theContext.DefaultContainerName, 
          DataSpace.CSpace); 

      return container.BaseEntitySets; 
    } 
    public static IEnumerable<ObjectQuery> GetObjectQueries(this ObjectContext theContext) 
    { 
     IEnumerable<ObjectQuery> queries = 
       from pd in theContext 
          .GetType() 
          .GetProperties() 
       where pd.PropertyType 
         .IsSubclassOf(typeof(ObjectQuery)) 
       select (ObjectQuery)pd.GetValue(theContext, null); 
     return queries; 
    } 
} 

Когда вы используете его:

IEnumerable<EntitySetBase> lookAtMe = context.GetEntitySets(); 
//ElementType (type of entity the set represents) 
//Entity Set Name 
//Other fun goodies ;) 

//Example of how to get the entity set to query on it. 
File f = new File(); 
//or some entity you selected. 
f = context.Files.FirstOrDefault(); 
string name = context.GetEntitySetName(f); 

Другой я ушел из был GetObjectQueries, и он просто возвращает все ObjectQueries, которые являются вещи в вашем контексте, что вы запрашиваете на , context.SomeTable или context.Products.

Я не уверен, что вы делаете, поэтому может быть лучший способ сделать это .... как только вы обновите конечную цель, я отредактирую соответствующим образом.

10

Этот пример кода из почтового What Tables Are In My EF Model? And My Database?

using (var dbContext = new YourDbContext()) 
{ 
    var metadata = ((IObjectContextAdapter)dbContext).ObjectContext.MetadataWorkspace; 

    var tables = metadata.GetItemCollection(DataSpace.SSpace) 
     .GetItems<EntityContainer>() 
     .Single() 
     .BaseEntitySets 
     .OfType<EntitySet>() 
     .Where(s => !s.MetadataProperties.Contains("Type") 
     || s.MetadataProperties["Type"].ToString() == "Tables"); 

    foreach (var table in tables) 
    { 
     var tableName = table.MetadataProperties.Contains("Table") 
      && table.MetadataProperties["Table"].Value != null 
      ? table.MetadataProperties["Table"].Value.ToString() 
      : table.Name; 

     var tableSchema = table.MetadataProperties["Schema"].Value.ToString(); 

     Console.WriteLine(tableSchema + "." + tableName); 
    } 
} 
+1

Это абсолютное лучшее решение – netfed

+1

... и если вы хотите перечислить свойства/поля таблиц/сущностей, вы можете запросить объект таблиц: var PropertiesInTables = tables.Select (s => s.ElementType.Properties) .К списку(); – netfed

Смежные вопросы