2010-10-08 33 views
17

Eso es todo. Es bastante simple. Tengo un edmx y quiero poder consultarlo dinámicamente para las tablas y (con suerte), compilar dinámicamente con esa tabla. ¿Es eso posible?Entity Framework - Obtener lista de tablas

=========

ACTUALIZACIÓN:

He incluido todas las tablas de datos, pero no hay puntos de vista o de SP, en el contexto. Tenemos muchas tablas que escriben información (con id). Entonces, por ejemplo, colores o tipo de archivo o tipo de protocolo. Quiero poder llevar a cabo una consulta de tipo (archivo) para las tablas que pueden contener la información de tipo (Archivo, Tipo de archivo) y devolverla con id.

Entonces, puedo buscar ... Business Unit (o Color, o Archivo) y el código se apagará y buscará el contexto para BusinessUnit (o Color o File) y BusinessUnitType (o ColorType o FileType). Si encuentra cualquiera de los dos, lo consultará y devolverá todas las filas para que pueda ver si contiene información de tipo (lo definiré más adelante para que solo devuelva los campos ID y Descripción, Abreviatura o Nombre, así como para limitar filas, etc.) y poder encontrar la identificación asociada para un particular en particular.

+2

Tablas o entidades? ¿Abstracto o concreto? Nombres o tipos? ¿Por qué? Por favor sea especifico. –

+0

Tablas - eso es todo. Solo tablas. El tipo de cosa que obtendrías al consultar sysobjects en SQL Server. – Michael

+0

¿Desea tablas en su contexto o en la base de datos? – Nix

Respuesta

13

Para su primera pregunta sobre cómo enumerar las tablas en la base de datos, este código las obtendrá para usted, por supuesto, las que se importaron a su EDM que necesariamente no son todas las tablas en su almacén de datos.

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

Este código se producirá un InvalidOperationException con este mensaje:
El espacio 'sspace' no tiene colección asociada
Y eso es porque a diferencia de CSpace, sspace (ssdl) no se carga hasta que esté necesario. y tratar de leerlos con MetadataWorkspace no cuenta como necesario. Es necesario durante la compilación de consultas, luego nuevamente en la materialización del objeto. Entonces, para engañar al MetadataWorkspace y cargarlo para nosotros, debemos ejecutar una consulta como la que se muestra a continuación justo antes de ejecutar la consulta principal que nos da los nombres de las tablas.

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

Puede leer más desde aquí: Quick Trick for forcing MetadataWorkspace ItemCollections to load

Sin embargo, si su intención es construir una consulta dinámica contra las tablas de tipo, entonces no es necesario perder el tiempo con sspace, hay que obténgalo del CSpace (Modelo Conceptual).A continuación se muestra un código de ejemplo sobre cómo construir una consulta dinámica con tener sólo una parte del nombre de la tabla:

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; 
    } 
} 


Código Explicación: Mi suposición era que sus nombres de tabla tipo se terminan en "Tipo" como un postfijo (por ejemplo, ColorType), por lo que puede llamar al GetAllType ("Color") y buscar ColorType EntityObject en su modelo y le dará todos los valores posibles. El código puede parecer aterrador, pero es bastante simple. Básicamente, todo lo que hace es obtener toda la información requerida de MetaData (como nombre de EntitySet, nombre de espacio de nombres, etc.) en función del parámetro del método y luego crear una consulta EntitySQL sobre la marcha, luego ejecutarla y devolver el resultados.

+2

¿Qué versión EF del código anterior por favor? Intenté en EF4.0, y "t => t.Name" ni siquiera se compila. Alguna solución? –

+0

Estoy usando EF 6.1.1 y este código funcionó para mí List tableList = db.MetadataWorkspace.GetItems (DataSpace.CSpace) .Select (x => x.Name); –

+0

Tengo el mismo problema de @LeiYang corregido con: var items = objectContext.MetadataWorkspace.GetItems (DataSpace.SSpace); – Evilripper

2

Por si esto ayuda, saqué esto de una de mis clases ObjectContextExtension.

Puede consultar el contexto de su objeto y obtener los nombres de la siguiente manera. Siéntete libre de modificar esto como quieras.

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; 
    } 
} 

Cuando usted lo utiliza:

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); 

El otro omití fue GetObjectQueries y que sólo se recuperan todos los ObjectQueries, que son las cosas en su contexto en el que se consulta en . context.SomeTable o context.Products.

No estoy seguro de lo que está haciendo, por lo que podría haber una mejor manera de hacerlo ... una vez que actualice su objetivo final lo editaré en consecuencia.

10

Este código de ejemplo desde el post 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

Esta es la mejor solución absoluta – netfed

+1

... y si desea enumerar las propiedades/campos de las tablas/entidades, puede consultar el objeto de tablas: var PropertiesInTables = tables.Select (s => s.ElementType.Properties) .Listar(); – netfed

Cuestiones relacionadas