2016-06-19 7 views
4

Ich versuche herauszufinden, wie Sie Werte aus einer Nachschlagetabelle mit Generics auswählen und zur Laufzeit den Entitätsnamen als Zeichenfolge übergeben. Hier ist was ich bisher habe. Das Problem, das ich habe, ist in den "var codes = Select();" Linie. Wie Sie sich vorstellen können, ist der Compiler nicht glücklich und gibt mir einen Fehler von: classType ist eine Variable, wird aber als Typ verwendet. Ich bin mir nicht sicher, was ich tun oder wie ich es beheben soll. Ich kann eine Schnittstelle oder einen Klassennamen nicht fest codieren, da ich die Signatur der Codetabelle erst dann kenne, wenn die Zeichenfolge aufgelöst ist. Jede Anleitung würde sehr geschätzt werden!Wie verwende ich Generics, um auf eine Entität in EF 6 zuzugreifen?

public void GetTableNameObject(string TableName) 
{ 
    dynamic classType = Activator.CreateInstance(Type.GetType(TypeName)); 
    var codes = Select<classType>(); 
} 

public IQueryable<TItem> Select<TItem>() where TItem : class, new() 
    { 
     PropertyInfo property = GetDbSet(typeof(TItem));  
     DbSet<TItem> set = property.GetValue(_context, null) as DbSet<TItem>;  
     return set; 
    } 

    private PropertyInfo GetDbSet(Type itemType) 
    { 
     var properties = typeof(CodeTableContext).GetProperties().Where(item => item.PropertyType.Equals(typeof(DbSet<>).MakeGenericType(itemType))); 

     return properties.First(); 
    } 
+0

Unterscheiden sich Ihre Tabellennamen von Entitätsnamen? und was meinst du mit "Lookup-Tabelle"? – Ashkan

Antwort

1

Ja, das ist Ursache classType eine dynamische Variable ist und generische Methode Typ T muss bei der Kompilierung geschlossen und nicht geöffnet halten werden kann, da die Art zum Zeitpunkt der Kompilierung selbst aufgelöst wird.

In Ihrem Fall, wie bereits erwähnt classType ist eine dynamische Variable und wird nur in der Laufzeit aufgelöst und Sie können es daher nicht als Typ auf generische Methode übergeben, da der Compiler nicht in der Lage sein wird, es bei der Kompilierung aufzulösen.

Sie könnten Reflection für diesen Zweck verwenden und einen Blick auf diesen Beitrag How do I use reflection to call a generic method?.

(OR) Anstelle eines dynamischen Typ, versuchen Sie es zu einem Ihrer Basistyp wie Gießen (nicht sicher, obwohl da keine Ahnung von Ihrer Klassenhierarchie haben)

IMyBase classType = Activator.CreateInstance(Type.GetType(TypeName)) as IMyBase; 
0

Ich denke, was Sie versuchen, do ist ein DbSet in einem Entity-Framework zu finden DbContext Objekt geben seinen Namen der Entität (unter der Annahme, dass Ihre Entitäten Namen nicht von Ihren Tabellennamen unterscheiden oder irgendwie können Sie eine durch die andere zu erreichen). Sie können keine generische Methode wie Select<TItem> where ... verwenden, da Sie den Typ TItem zum Zeitpunkt der Kompilierung kennen müssen (dh wenn Sie Ihren Code schreiben).

Das wichtigere Problem ist, dass Sie versuchen, rückgängig machen welche Entity Framework hat für Sie erledigt! EF hat alles (Tabellen und Spalten) für Sie stark typisiert, aber Sie wollen das nicht und verwenden Zeichenfolgen und Literale wie bei der Verwendung von ADO.Net. Ich bin geneigt, Ihnen vorzuschlagen, SQL-Befehle zu verwenden und Ihre Abfrage mit SQL-Anweisungen zu machen, aber es hängt von Ihrer Anwendung ab und davon, wann diese Methode aufgerufen wird und so viele andere Faktoren.

In der Tat gibt es mehrere Optionen, die Sie Ihre DbSet von Ihrem Entitätsname bekommen können, einer von ihnen ist, dass Sie ein Wörterbuch Ihrer Entitätsnamen auf Ausdrücke abgebildet schaffen, die die entsprechenden DbSet aber wieder zurück, wenn Sie nicht wissen, der type in compile type wäre nicht sehr brauchbar, was bedeutet, dass du linq nicht für diesen db-satz verwenden kannst, weil linq stark typisierte syntax verwendet. Wie auch immer das ist, was ich vorschlagen, die nicht eine große Lösung, aber es funktioniert:

Dictionary<string, Func<CodeTableContext, DbSet>> entityDbSetMap = new Dictionary<string, Func<EFDB, DbSet>> 
{ 
    { "ProductEntity", (db) => db.ProductEntities }, 
    { "OrderEntity", (db) => db.OrderEntities }, 
    { "FooEntity", (db) => db.FooEntities }, 
    { "BarEntity", (db) => db.BarEntities }, 
    // more mappings ...... 
} 

public IQueryable GetTableNameObject(string EntityName) 
{ 
    DbSet dbset = entityDbSetMap[entityName](_context); 
    return dbset.AsQueryable(); 
} 

diese Weise können Sie nur einen dynamisch erstellte Ausdruck auf dem abfragbaren-Objekt verwenden können, die erhalten wird, was könnte das sein, was Sie tun mögen.

Hoffe, das hilft.

Verwandte Themen