2017-05-26 5 views
2

0 zu transformieren. Ich übergebe eine Zeichenfolge mit dem Namen des Entitätstyps, den ich abfragen möchte, und erhalte den Typ basierend auf der Zeichenfolge. Ich möchte die DbSet zurück erhalten und eine IQueryable zurückgeben. Das Problem ist, wo ich (DbSet<tableEntity>) tue und die folgende Fehlermeldung erhalten:X ist eine Variable, wird aber wie ein Typ verwendet, wenn versucht wird,

tableEntity is a variable but used like a type

wenn zu werfen versucht. Gibt es eine Möglichkeit, dies zu lösen?

public object GetList(string tableEntity) 
{ 
    Type tableEntity = Type.GetType("TestProject." + typeName + ", TestProject"); 

    var dbObject = (DbSet<tableEntity>)typeof(DbContext).GetMethod("Set", Type.EmptyTypes) 
         .MakeGenericMethod(tableEntity) 
         .Invoke(databaseContext, null); 

    return dbObject.AsQueryable();    
} 

EDIT

Gerade habe ich nicht auf den Typ Zugriff hinzuzufügen, die wir ich bin ist vorbei, den Namen durch einen String.

+0

Der Unterschied zwischen der Kompilierung und Laufzeit ist sehr wichtig! Wenn du es nicht kaputt machst, stolpertst du ständig über so schlimme Fallstricke wie diese. [Lesen Sie eine Einführung in Compiler.] (Https://meta.stackexchange.com/questions/25840/can-we-stop-recommending-the-dragon-book-please) Es ist das Werkzeug, mit dem Sie professionell arbeiten, Sie sollte wissen, wie es im Prinzip funktioniert, wenn nicht im Detail. –

+0

Sie können die folgenden nützlich finden, wenn die DB MS Sql Server ist oder die gleichen Datentypdefinitionen hat: https://stackoverflow.com/a/28561947/4228193. System.Web aller Orte. Ich verwende es wie folgt 'TypeCode systc = Parameter.ConvertDbTypeToTypeCode ([SqlMetaData_instance] .DbType); versuchen { Rückgabe Convert.ChangeType (val, systc); } ' – mpag

Antwort

4

So stellt sich heraus, dass der Entitätstyp zur Kompilierungszeit buchstäblich nicht bekannt oder bekannt ist. Es muss eine Zeichenfolge sein.

Der einzige Ort, an dem Sie den Typ zum Zeitpunkt der Kompilierung verwenden, ist in der Besetzung (DbSet<tableEntity>). Nun, du brauchst das vielleicht nicht. Alles, was Sie von diesem Typ benötigen, ist der Aufruf AsQueryable(), und AsQueryable() ist eine Erweiterungsmethode für IEnumerable, mit generischen und nicht-generischen Versionen. Wenn wir es durch nicht-generische IEnumerable aufrufen, das ist nicht-generisch AsQueryable(), die nicht generische IQueryable zurückgibt. Aber wir geben sowieso object zurück, also hey. Damit das Ergebnis dieser Sache nützlich ist, muss etwas irgendwo eine Reflexion darüber anstellen, so dass der erklärte Typ wahrscheinlich von geringer Bedeutung ist.

sehen, ob das funktioniert:

public object GetList(string tableEntity) 
{ 
    Type tableEntity = Type.GetType("TestProject." + typeName + ", TestProject"); 

    var dbObject = (System.Collections.IEnumerable) 
         typeof(DbContext).GetMethod("Set", Type.EmptyTypes) 
         .MakeGenericMethod(tableEntity) 
         .Invoke(databaseContext, null); 

    return dbObject.AsQueryable();    
} 

Wenn Sie generische IQueryable<TEntityType> brauchen sich herausstellt, werden wir haben Reflektion verwenden MethodInfo für AsQueryable<TEntityType> für das Unbekannte zu erhalten (zum Zeitpunkt der Kompilierung) Entitätstyp und Anruf MakeGenericMethod(tableEntity) auf das.


Erster Versuch:

In der Sprache, geben Sie Parameter für Generika müssen tatsächlichen Typen, nicht Instanzen der Type Klasse sein. Das liegt daran, dass sie zur Kompilierzeit aufgelöst werden.

Aber das ist kein Problem; Um einen Typparameter an eine generische Methode zu übergeben, schreiben Sie einfach eine generische Methode mit einem Typparameter.

Sie können dies nicht tun:

var stuff = GetList("MyTableEntityClass"); 

Aber das ist nur so gut:

var stuff = GetList<MyTableEntityClass>(); 

...

public object GetList<TTableEntity>() 
{ 
    var dbObject = (DbSet<TTableEntity>)typeof(DbContext) 
         .GetMethod("Set", Type.EmptyTypes) 
         .MakeGenericMethod(typeof(TTableEntity)) 
         .Invoke(databaseContext, null); 

    return dbObject.AsQueryable();    
} 

Reflexion unterscheidet; deshalb übergeben wir typeof(TTableEntity) zu MakeGenericMethod().

Und wenn wir eine tatsächliche Art verwenden, dass der Compiler überprüfen können, können wir es besser machen mit unserem Rückgabetyp zu:

public IQueryable<TTableEntity> GetList<TTableEntity>() 
{ 
    var dbObject = (DbSet<TTableEntity>)typeof(DbContext) 
         .GetMethod("Set", Type.EmptyTypes) 
         .MakeGenericMethod(typeof(TTableEntity)) 
         .Invoke(databaseContext, null); 

    return dbObject.AsQueryable();    
} 
+0

Das Problem mit dieser Lösung ist, ich habe keinen Zugriff auf den Typ oder ich würde es auf diese Weise getan. Die Situation, in der ich mich jetzt befinde, ist, dass die BAL durch die DAL gehen muss, um zu Entity Framework-Objekten zu gelangen. Entschuldigung, ich denke, das sollte zu meiner Frage hinzugefügt werden. – Kogroth

+0

@Kogroth Oh mein Gott, das kann unglaublich einfach sein. –

+0

@ Kogroth Siehe Update. Lass es mich wissen, wenn das funktioniert. –

0

Da, wie Ed erwähnt, müssen Sie die Tabelle nicht verwenden Entitätstyp zur Kompilierzeit, warum nicht einfach die nicht-generische databaseContext.Set (tableEntity).AsQueryable() verwenden? Aber wenn Sie Ihr Herz auf Set<> festgelegt haben, versuchen Sie dies:

public object GetList(string tableEntity) 
{ 
    Type tableEntity = Type.GetType("TestProject." + typeName + ", TestProject"); 

    return GetType() 
     .GetMethod ("GetListHelper") 
     .MakeGenericMethod (tableEntity) 
     .Invoke (this) ; 
} 

public object GetListHelper<T>() where T : class 
{ 
    var dbObject = databaseContext.Set<T> (null) ; 
    return dbObject.AsQueryable();    
} 
Verwandte Themen