Entity Framework - Obtenir la liste des tables

entity-framework

Question

C'est tout. C'est assez simple. J'ai un edmx et je veux pouvoir l'interroger dynamiquement pour des tables et, espérons-le, le construire dynamiquement contre cette table. Est-ce possible?

=========

METTRE À JOUR:

J'ai inclus toutes les tables de base de données, mais pas de vues ni de SP, dans le contexte. Nous avons beaucoup de tables de type info (avec les identifiants). Ainsi, par exemple, les couleurs ou le type de fichier ou le type de protocole. Je veux pouvoir prendre une requête de type (fichier) pour des tables pouvant contenir le type info (File, FileType) et la renvoyer avec un identifiant.

Donc, je vais peut-être chercher ... Business Unit (ou Color, ou File) et le code s'éteindra et recherchera le contexte pour BusinessUnit (ou Color ou File) et BusinessUnitType (ou ColorType ou FileType). S'il en trouve un, il l'interrogera et renverra toutes les lignes afin que je puisse voir s'il contient des informations de type (je l'affinerai ultérieurement pour ne renvoyer que les champs ID et Description, Abréviation ou Nom, ainsi que les lignes de limitation, etc.) et être capable de trouver l'ID associé pour un particulier.

Réponse acceptée

Pour votre première question sur la façon d’énumérer les tables de la base de données, ce code les obtiendra pour vous, bien entendu celles qui ont été importées dans votre EDM, qui ne correspondent pas nécessairement à toutes les tables de votre magasin de données.

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

Ce code provoquera une InvalidOperationException avec ce message:
L'espace 'SSpace' n'a pas de collection associée
Et c’est parce que contrairement à CSpace, SSpace (ssdl) n’est pas chargé tant que cela n’est pas nécessaire. et essayer de les lire avec MetadataWorkspace ne compte pas comme étant nécessaire. Il est nécessaire lors de la compilation de la requête, puis à nouveau lors de la matérialisation de l'objet. Donc, pour tromper MetadataWorkspace et le charger pour nous, nous devons exécuter une requête comme ci-dessous juste avant la requête principale qui nous donne des noms de table.

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

Vous pouvez en lire plus ici: tour rapide pour forcer le chargement de MetadataWorkspace ItemCollections

Cependant, si votre intention est de créer une requête dynamique sur vos tables de types, vous n'avez pas besoin de perdre son temps avec SSpace, vous devez l'obtenir à partir de CSpace (modèle conceptuel). Voici un exemple de code sur la manière de créer une requête dynamique avec seulement une partie du nom de la table:

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


Explication de code: Mon hypothèse était que vos noms de table de type se terminent par "Type" en tant que postfixe (par exemple, ColorType). Vous pouvez donc appeler GetAllType ("Color") et le rechercher dans ColorType EntityObject dans votre modèle. valeurs possibles. Le code peut sembler effrayant, mais c'est assez simple. Fondamentalement, il récupère toutes les informations requises à partir de MetaData (comme le nom EntitySet, le nom d’espace de nom, etc.) en fonction du paramètre de méthode, puis crée une requête EntitySQL à la volée, puis exécute-la et renvoie le résultats.


Réponse populaire

Cet exemple de code de post Quelles sont les tables dans mon modèle EF? Et ma base de données?

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


Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow