2010-07-25 1 views
6

J'ai créé un ObjectSet<T> générique dans mon référentiel générique.Comment obtenir ObjectSet <T> Nom de la clé d'entité?

Ce que je voudrais obtenir est le name de l'EntityKey de ObjectSet<T> de sorte que je puisse l'employer dans le DataContext.GetObjectByKey.

J'ai cherché autour et creusé profondément, mais je ne peux pas sembler trouver cette valeur n'importe où dans la classe ObjectSet.

Répondre

5

J'ai regardé il y a un moment pour un bon moyen de le faire et je n'ai pas réussi à en trouver un. Je finis généralement par construire une méthode d'extension GetEntityByKey quelque part et dedans, contatenating des chaînes pour construire des clés d'entité pour les appels TryGetObjectByKey. L'idée générale pour construire la clé d'entité va quelque chose comme ceci:

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     var dc = new AdventureWorksLT2008Entities(); 
     object c; 
     dc.TryGetObjectByKey(GetEntityKey(dc.Customers, 23), out c); 
     var customer = c as Customer; 
     Console.WriteLine(customer.EmailAddress); 
    } 

    private static EntityKey GetEntityKey<T>(ObjectSet<T> objectSet, object keyValue) where T : class 
    { 
     var entitySetName = objectSet.Context.DefaultContainerName + "." + objectSet.EntitySet.Name; 
     var keyPropertyName = objectSet.EntitySet.ElementType.KeyMembers[0].ToString(); 
     var entityKey = new EntityKey(entitySetName, new[] {new EntityKeyMember(keyPropertyName, keyValue)}); 
     return entityKey; 
    } 
} 

Vous pouvez faire quelque chose de similaire. Cet exemple suppose un seul champ par EntityKey pour plus de simplicité - pour les clés à valeurs multiples, vous devrez faire quelque chose de légèrement plus sophistiqué avec ObjectSet<T>.ElementType.KeyMembers et transmettre toutes vos clés dans le constructeur EntityKey.

1

Voir this post que j'ai fait concernant l'obtention de l'EntitySetName. Pour mon référentiel, je crée une propriété qui obtient le nom de l'ensemble d'entités pour le nom de classe spécifique pour faire exactement ce que vous essayez de faire.

2

Générique:

public class GenericoRepositorio<T> : IGenericoRepositorio<T> where T : class 
{ 
    protected readonly ObjectSet<T> ObjetoSet; 
    protected readonly ModeloContainer Contexto; 

    public GenericoRepositorio(ModeloContainer contexto) 
    { 
     Contexto = contexto; 
     ObjetoSet = Contexto.CreateObjectSet<T>(); 
    } 

    public T Carregar(int id) 
    { 
     object objeto; 
     Contexto.TryGetObjectByKey(GetEntityKey(ObjetoSet, id), out objeto); 
     return (T)objeto; 
    } 

    private static EntityKey GetEntityKey<T>(ObjectSet<T> objectSet, object keyValue) where T : class 
    { 
     var entitySetName = objectSet.Context.DefaultContainerName + "." + objectSet.EntitySet.Name; 
     var keyPropertyName = objectSet.EntitySet.ElementType.KeyMembers[0].ToString(); 
     var entityKey = new EntityKey(entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) }); 
     return entityKey; 
    } 
} 
1

Cela devrait vous donner tous les arguments génériques (types) pour le ObjectSet:

objectSet.GetType().GetGenericArguments().First() 
0

J'ai eu un moment difficile essayer de faire presque la même chose, obtenir le nom et la valeur de la clé primaire au moment de l'exécution lorsque le type est inconnu. J'essayais juste de mettre en place un système d'audit pour les suppressions, et chaque solution que je trouve implique un code superflu que je ne comprends pas vraiment. L'EntityKey n'est pas disponible à partir d'un DbContext, ce qui est également déroutant et ennuyant. Les 5 dernières lignes peuvent vous faire économiser 5 heures et 1 an de calvitie. Je ne suis pas en train d'essayer ceci pour les Inserts, donc si vous le faites, vous devez inspecter ces valeurs avec soin car elles peuvent être nulles ou nulles.

foreach(var entry in ChangeTracker.Entries<IAuditable>()) 
{ 
... 

case EntityState.Deleted: 

var oc = ((IObjectContextAdapter)this).ObjectContext; //this is a DbContext 
EntityKey ek = oc.ObjectStateManager.GetObjectStateEntry(entry.Entity).EntityKey; 
var tablename = ek.EntitySetName; 
var primaryKeyField = ek.EntityKeyValues[0].Key;  //assumes only 1 primary key 
var primaryKeyValue = ek.EntityKeyValues[0].Value; 
+0

Que faire si vous n'avez pas de ChangeTracker.Entries? – ProfK

+0

Dans mon cas, j'ai été accroché dans l'événement SaveChanges et je n'ai pas désactivé le suivi des modifications. Si votre suivi des modifications est désactivé, la réponse marquée devrait vous aider. Si votre suivi des modifications n'est pas désactivé, et que vous avez un contrôle sur une entité, je pense que vous pourriez le sous-traiter dans ma deuxième ligne où je mets '(entry.Entity)'. – Bill

0

var objContext = ((IObjectContextAdapter)this.context).ObjectContext;

var objSet = objContext.CreateObjectSet<T>();

var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entityToUpdate);

Object foundEntity;

var exits = objContext.TryGetObjectByKey(entityKey, out foundEntity);

if (exits && this.dbset.Local != null && this.dbset.Local.Contains(foundEntity) &&this.dbset.Local.Any())      
{ 
    if (entityKey.EntityKeyValues != null && entityKey.EntityKeyValues.Any())      
    {  
    DbEntityEntry<T> entry = this.context.Entry(this.dbset.Find(entityKey.EntityKeyValues.FirstOrDefault().Value)); 
         entry.CurrentValues.SetValues(entityToUpdate); 
    } 
} 

this.context.SaveChanges(); 
0

Testé avec EF 6.

Il retourne un tableau d'objets pour chaque valeur de clé primaire pour le DbEntityEntry donné.

Leurs cas de bord peut-être où cela ne fonctionne pas - mais pour mes besoins simples fonctionne très bien.

J'espère que cela aidera quelqu'un d'autre.

object[] GetPrimaryKeyValue(DbEntityEntry entry) 
{ 
    List<object> key = new List<object>(); 

    var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity); 
    if (objectStateEntry.EntityKey.EntityKeyValues != null && objectStateEntry.EntityKey.EntityKeyValues.Length==1) 
    { 
     key.Add(objectStateEntry.EntityKey.EntityKeyValues[0].Value); 
    } 
    else 
    { 
     if (objectStateEntry.EntitySet.ElementType.KeyMembers.Any()) 
     { 
      foreach (var keyMember in objectStateEntry.EntitySet.ElementType.KeyMembers) 
      { 
       if (entry.CurrentValues.PropertyNames.Contains(keyMember.Name)) 
       { 
        var memberValue = entry.CurrentValues[keyMember.Name]; 
        if (memberValue != null) 
        { 
         key.Add(memberValue); 
        } 
       } 
      } 
     } 
    } 
    return key.ToArray(); 
} 
Questions connexes