Suchen Sie dynamisch nach einem generischen DbSet in einem DbContext

.net asp.net-mvc-5 c# entity-framework-core

Frage

Ich weiß, dass diese Frage bereits gestellt wurde, aber ich konnte keine Antwort finden, die mich zufrieden stellte. Was ich versuche, ist, ein bestimmtes DbSet<T> basierend auf dem Typ seines Namens DbSet<T> .

Ich habe folgendes:

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyDllAssemblyName")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyCallingAssemblyName")]

class MyDbContext : DbContext {

    public DbSet<ModelA> A { get; set; }
    public DbSet<ModelB> B { get; set; }

    public dynamic GetByName_SwitchTest(string name) {
        switch (name) {
            case "A": return A;
            case "B": return B;
        }
    }

    public dynamic GetByName_ReflectionTest(string fullname)
    {
        Type targetType = Type.GetType(fullname);
        var model = GetType()
            .GetRuntimeProperties()
            .Where(o => 
                o.PropertyType.IsGenericType &&
                o.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
                o.PropertyType.GenericTypeArguments.Contains(targetType))
            .FirstOrDefault();
        if (null != model)
            return model.GetValue(this);
        return null;
    }
}

Ich habe keine Probleme, den Typ selbst zu bekommen, ob es über einen einfachen Schalter oder eine Reflexion ist. Ich muss jedoch den Typ als dynamisch zurückgeben, da ich nicht weiß, um welchen DbSet-Typ es sich handelt. Dann woanders in derselben Versammlung, ich benutze es so:

// MyDbContext MyDbContextInstance..
var model = MyDbContextInstance.GetByName_SwitchTest("A");
var record1 = model.FirstOrDefault(); // It crashes here with RunTimeBinderException

An diesem Punkt enthält das model eine Instanz eines InternalDbSet<ModelA> . Von dort jede Anwendung ich mit dem tun model bekomme ich Objekt eine RunTimeBinderException: ‚Microsoft.Data.Entity.Internal.InternalDbSet‘ enthält keine Definition für ‚FirstOrDefault‘ enthalten

Als ich im Web nachforschte, fand ich einen Blog-Beitrag , der das erklärte (dixit sein Blog):

Der Grund für den Aufruf von FirstOrDefault () ist, dass die Typinformationen des Modells zur Laufzeit nicht verfügbar sind. Der Grund dafür ist, dass anonyme Typen nicht öffentlich sind. Wenn die Methode eine Instanz dieses anonymen Typs zurückgibt, gibt sie ein System.Object zurück, das auf eine Instanz eines anonymen Typs verweist - ein Typ, dessen Informationen dem Hauptprogramm nicht zur Verfügung stehen.

Und dann zeigt er, dass eine Lösung:

Die Lösung ist eigentlich ganz einfach. Alles, was wir tun müssen, ist, AssemblyInfo.cs des ClassLibrary1-Projekts zu öffnen und folgende Zeile hinzuzufügen: [assembly:InternalsVisibleTo("assembly-name")]

Ich habe diese Lösung auf meinem Code versucht, aber es funktioniert nicht. Für Informationen habe ich eine asp.net 5 Lösung mit zwei Assemblys, die auf dnx dotnet46 laufen. Eine App und eine DLL, die alle meine Modelle und DbContext enthält. Alle betroffenen Anrufe, die ich mache, befinden sich jedoch auf der DLL.

Hat diese Lösung eine Chance zu arbeiten? Fehle ich etwas? Irgendwelche Zeiger würden sehr geschätzt werden?

Danke im Voraus

[BEARBEITEN]

Ich habe versucht, IQueryable<dynamic> anstelle von dynamic und ich konnte das grundlegende Abfragemodell model.FirstOrDefault(); aber vor allem möchte ich auch auf ein Feld filtern können:

var record = model.FirstOrDefault(item => item.MyProperty == true);

Beliebte Antwort

Also wie habe ich es gemacht, wenn ich <T> während der Kompilierzeit nicht bemerkt habe.

Zuerst muss der Typ als DbContext.Set- Methode abgerufen werden, um eine nicht generische DbSet-Instanz für den Zugriff auf Entitäten des angegebenen Typs im Kontext und dem zugrunde liegenden Speicher zurückzugeben.

public virtual DbSet Set(Type entityType)

Hinweis here Argument ist der Typ der Entität, für die eine Menge zurückgegeben werden soll. Für den angegebenen Entitätstyp ist der Rückgabewert festgelegt.

var type = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(t => t.Name == <Pass your table name>);

Jetzt habe ich einmal diesen Typ

if(type != null)
{
DbSet context = context.Set(type);
}

Oder ein One Liner wäre

DbSet mySet = context.Set(Type.GetType("<Your Entity Name>"));


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum