56 votes

Obtenir le nom de la table de base de données à partir des métadonnées Entity Framework

J'essaie de trouver un moyen pour obtenir le nom de la table SQL sous-jacente pour un type d'entité donnée. J'ai expérimenté avec les MetadataWorkspace requêtes et alors que je peux obtenir beaucoup d'informations à partir de l'objet ou de l'espace de stockage, je n'arrive pas à comprendre comment la carte entre les deux.

Donc, dire que je suis un type dans le modèle d'objet appelé de Recherche - comment puis-je trouver le nom de la table (wws_lookups) dans la base de données?

Je peux interroger tous les EntityType objets pour CSpace et SSpace et je peux voir les deux correctement, mais je ne peux pas comprendre comment obtenir SSpace de CSpace.

Est-il possible de faire cela?

42voto

Rui Jarimba Points 3243

Je sais que ce post est assez vieux, mais je vais mettre ici ma solution, il peut être utile pour quelqu'un. Je suis l'aide de Nigel de l'approche (l'extraction du nom de la table à partir d' .ToTraceString()), mais avec quelques modifications, parce que son code ne fonctionne pas si la table n'est pas par défaut dans le schéma SQL Server (dbo.{table-name}).

J'ai créé des méthodes d'extension pour DbContext et ObjectContext objets:

public static class ContextExtensions
{
    public static string GetTableName<T>(this DbContext context) where T : class
    {
        ObjectContext objectContext = ((IObjectContextAdapter) context).ObjectContext;

        return objectContext.GetTableName<T>();
    }

    public static string GetTableName<T>(this ObjectContext context) where T : class
    {
        string sql = context.CreateObjectSet<T>().ToTraceString();
        Regex regex = new Regex("FROM\s+(?<table>.+)\s+AS");
        Match match = regex.Match(sql);

        string table = match.Groups["table"].Value;
        return table;
    }
}

Plus de détails ici:
Entity Framework: Obtenir mappé nom de la table à partir d'une entité

30voto

Colin Points 5006

MODIFIER Cette réponse, désormais obsolète, en raison de la nouvelle fonctionnalité en EF 6.1 : mise en correspondance entre les types de table

J'ai eu un problème avec les autres réponses, car j'ai un type dérivé. J'ai reçu cette méthode (à l'intérieur de ma classe de contexte) pour travailler - j'ai une seule couche de l'héritage dans mon modèle pour le moment

private readonly static Dictionary<Type, EntitySetBase> _mappingCache 
       = new Dictionary<Type, EntitySetBase>();

private ObjectContext _ObjectContext
{
    get { return (this as IObjectContextAdapter).ObjectContext; }
}

private EntitySetBase GetEntitySet(Type type)
{
    if (_mappingCache.ContainsKey(type))
        return _mappingCache[type];

    type = GetObjectType(type);
    string baseTypeName = type.BaseType.Name;
    string typeName = type.Name;

    ObjectContext octx = _ObjectContext;
    var es = octx.MetadataWorkspace
                    .GetItemCollection(DataSpace.SSpace)
                    .GetItems<EntityContainer>()
                    .SelectMany(c => c.BaseEntitySets
                                    .Where(e => e.Name == typeName 
                                    || e.Name == baseTypeName))
                    .FirstOrDefault();

    if (es == null)
        throw new ArgumentException("Entity type not found in GetEntitySet", typeName);

    return es;
}

internal String GetTableName(Type type)
{
    EntitySetBase es = GetEntitySet(type);

    //if you are using EF6
    return String.Format("[{0}].[{1}]", es.Schema, es.Table);

    //if you have a version prior to EF6
    //return string.Format( "[{0}].[{1}]", 
    //        es.MetadataProperties["Schema"].Value, 
    //        es.MetadataProperties["Table"].Value );
}

internal Type GetObjectType(Type type)
{
    return System.Data.Entity.Core.Objects.ObjectContext.GetObjectType(type);
}

NB Il y a des plans pour améliorer l'API de Métadonnées et si ce n'est pas d'obtenir ce que nous voulons, alors nous pouvons regarder EF Premier Code de Mappage Entre des Types et des Tableaux

6voto

Alex James Points 15939

Non, malheureusement, il est impossible à l'aide de l'Api de Métadonnées pour obtenir le nom de la table pour une entité donnée.

C'est parce que le Mappage des métadonnées n'est pas public, donc il n'y a aucun moyen de passer de C-Espace de S-l'Espace à l'aide de l'EF de l'Api.

Si vous avez vraiment besoin pour ce faire, vous pouvez toujours construire la carte vous-même par l'analyse de la MSL. Ce n'est pas pour les faibles de cœur, mais il devrait être possible, sauf si vous utilisez QueryViews (qui sont très rares), à quel point il est à toutes fins utiles impossible (vous pouvez analyser ESQL... argh!)

Alex James

Microsoft.

6voto

Nigel Findlater Points 51

Il y a un moyen de supprimer les données à l'aide de EF sans avoir à le charger d'abord je l'ai décrit dans un peu plus de détenir en: http://nigelfindlater.blogspot.com/2010/04/how-to-delete-objects-in-ef4-without.html

L'astuce consiste à jeter la IQueriable dans un ObjectQuery et l'utilisation de la méthode ToTraceString. Puis modifier la résultante d'une chaîne sql. Cela fonctionne, mais vous devez être prudent parce que vous êtes en contournant les mécanismes qui EF a mis en place pour le maintien de dépendances et les contraintes. Mais pour des raisons de performances, je pense que c'est ok pour ce faire....

avoir du plaisir...

Nigel...

    private string GetClause<TEntity>(IQueryable<TEntity> clause) where TEntity : class 
    { 
        string snippet = "FROM [dbo].["; 

        string sql = ((ObjectQuery<TEntity>)clause).ToTraceString(); 
        string sqlFirstPart = sql.Substring(sql.IndexOf(snippet)); 

        sqlFirstPart = sqlFirstPart.Replace("AS [Extent1]", ""); 
        sqlFirstPart = sqlFirstPart.Replace("[Extent1].", ""); 

        return sqlFirstPart; 
    } 

   public void DeleteAll<TEntity>(IQueryable<TEntity> clause) where TEntity : class 
    { 
        string sqlClause = GetClause<TEntity>(clause); 
        this.context.ExecuteStoreCommand(string.Format(CultureInfo.InvariantCulture, "DELETE {0}", sqlClause)); 
    } 

3voto

Craig Stuntz Points 95965

Une solution de contournement possible (pas génial, mais les alternatives non plus ...):

 var sql = Context.EntitySetName.ToTraceString();
 

... puis analyser le SQL, ce qui devrait être assez simple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X