2010-07-25 1 views
6

Ich habe eine generische ObjectSet<T> in meinem generischen Repository erstellt.Wie erhält man ObjectSet <T> 's Entity Key Name?

Was ich möchte, ist die name des EntityKey von ObjectSet<T>, so dass ich es in der DataContext.GetObjectByKey verwenden kann.

Ich habe gesucht und tief gegraben, aber ich kann diesen Wert nirgends in der ObjectSet Klasse finden.

Antwort

5

Ich sah vor einer Weile für eine nette Möglichkeit, dies zu tun und konnte nicht finden. Im Allgemeinen erstelle ich am Ende eine GetEntityByKey-Erweiterungsmethode und bringe damit die Strings zusammen, um Entity Keys für TryGetObjectByKey-Aufrufe zu erstellen. Die allgemeine Idee zum Erstellen des Entitätsschlüssels lautet etwa folgendermaßen:

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

Möglicherweise können Sie etwas Ähnliches tun. In diesem Beispiel wird zur Vereinfachung ein einzelnes Feld pro EntityKey vorausgesetzt - für Schlüssel mit mehreren Werten müssten Sie etwas anspruchsvolleres mit ObjectSet<T>.ElementType.KeyMembers machen und alle Ihre Schlüssel in den EntityKey-Konstruktor übergeben.

1

Siehe this post, die ich hinsichtlich des Erhaltens des EntitySetName gemacht habe. Für mein Repository erstelle ich eine Eigenschaft, die den Namen des Entity-Sets für den spezifischen Klassennamen dazu bringt, genau das zu tun, was Sie tun möchten.

2

Allgemein:

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

Dies sollte Ihnen alle generischen Argumente (die Typen) für die ObjectSet:

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

hatte ich eine harte Zeit fast die gleiche Sache zu tun versuchen, immer Name und Wert des Primärschlüssels zur Laufzeit, wenn der Typ unbekannt ist. Ich habe gerade versucht, ein Prüfschema für Löschungen zu implementieren, und jede Lösung, die ich finde, beinhaltet überflüssigen Code, den ich nicht wirklich verstehe. Der EntityKey ist nicht von einem DbContext verfügbar, was auch verwirrend und ärgerlich ist. Die letzten 5 Zeilen können Ihnen 5 Stunden und 1 Jahr Haarausfall ersparen. Ich versuche dies nicht für Einfügungen. Wenn Sie dies tun, müssen Sie diese Werte sorgfältig prüfen, da sie 0 oder null sein können.

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

Was ist, wenn Sie keine ChangeTracker.Entries haben? – ProfK

+0

In meinem Fall wurde ich in das Ereignis SaveChanges eingebunden und deaktivierte das Änderungs-Tracking nicht. Wenn Ihre Änderungsverfolgung deaktiviert ist, sollte Ihnen die markierte Antwort helfen. Wenn Ihre Änderungsverfolgung nicht deaktiviert ist und Sie eine Entität verwalten, würde ich meinen, dass Sie diese in meiner zweiten Zeile subtrahieren könnten, wo ich '(entry.Entity)' eingegeben habe. – 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

Getestet mit EF 6.

Es wird ein Array von Objekten für jeden Primärschlüsselwert für den angegebenen DbEntityEntry zurückgegeben.

Ihre vielleicht Rand Fälle, wo dies nicht funktioniert - aber für meine einfachen Bedürfnisse funktioniert super.

Hoffe das hilft jemand anderem.

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(); 
} 
Verwandte Themen