5

Ich habe eine Basisklasse und zwei abgeleitete Klassen.Entity Framework fragt abgeleitete Klassen nicht ab - Fehler in DbOfTypeExpression

Jede der abgeleiteten Klassen implementiert den gleichen Typ wie eine Eigenschaft - der einzige Unterschied ist der Name der Eigenschaft.

Leider habe ich nicht viel Einfluss auf das Klassen-Design -> sie wurden aus einer WSDL-Datei generiert.

Ich habe dann eine Eigenschaft auf dem BaseType, um die gemeinsame Eigenschaft einzukapseln. Der Plan war, diese Eigenschaft in meinen Web-Ansichten verwenden usw.

ich das berühmte „Fruit-Beispiel“ verwendet habe, um das Problem zu demonstrieren:

public class FruitBase 
    { 
     public virtual int ID { get; set; } 


     // 
     // The plan is to use this property in mvc view 
     // 
     [NotMapped] 
     public virtual FruitnessFactor Fruitness 
     { 
      get 
      { 
       if (this.GetType().BaseType == typeof(Apple)) 
        return ((Apple)this).AppleFruitness; 
       else if (this.GetType().BaseType == typeof(Orange)) 
        return ((Orange)this).OrangeFruitness; 
       else 
        return null; 
      } 
     } 
    } 

public class FruitnessFactor { } 

In meinen MVC-Controller, die folgende Abfrage funktioniert absolut in Ordnung

return View(context.FruitEntities 
          .OfType<Apple>().Include(a =>a.AppleFruitness) 
          .ToList()); 

Aber dieses nicht:

return View(context.FruitEntities 
            .OfType<Apple>().Include(a =>a.AppleFruitness) 
            .OfType<Orange>().Include(o => o.OrangeFruitness) 
            .ToList()); 

Die Fehlermeldung erhalte ich ist :

DbOfTypeExpression erfordert ein Ausdrucksargument mit einem polymorphen Ergebnistyp, der mit dem Argument type kompatibel ist.

Ich verwende EF 5.0 RC und den Code First Ansatz.

Jede Hilfe wird sehr geschätzt!

+3

Diese vielleicht, weil Ihr Ausdruck bedeutet 'Orange' ist ein' Apfel' – Eranga

+0

Ich hätte gedacht, indem ich meine FruitEntities als 'DbSet definiert habe FruitEntities der Ausdruck impliziert, dass Orange und Apple Früchte sind ?! – Flo

+0

Die "OfType" -Kette sagt: "Alle Äpfel aus den FruitEntities filtern und dann aus dem Ergebnis alle Äpfel filtern, die Orangen sind", was nur Sinn ergibt, wenn Orangen Äpfel sind, d. H. 'Orange' Klasse erbt von' Apfel' Klasse. Was möchten Sie mit dieser Abfrage erreichen? Eine kombinierte Liste von Orangen und Äpfeln, d.h. alle Früchte, die Äpfel ** oder ** Orangen sind? – Slauma

Antwort

7

Soweit ich sagen kann Sie Include nicht auf mehrere Subtypen in einer einzigen Datenbankabfrage anwenden. Sie können einen Typ (OfType<Apple>().Include(a => a.AppelFruitness)) und denselben für einen anderen Subtyp abfragen. Das Problem besteht darin, dass Sie die Ergebnisse nicht in derselben Abfrage zusammenfassen können, da die Ergebnissammlungen unterschiedliche generische Typen (Äpfel und Orangen) aufweisen.

Eine Option wäre, zwei Abfragen auszuführen und die Ergebnissammlung in eine neue Sammlung des Basistyps zu kopieren - wie Sie bereits im Kommentarbereich unter Ihrer Frage angegeben haben.

Die andere Option (die nur eine einzige Abfrage benötigen würde) ist eine Projektion. Sie müssten einen Projektionstyp definieren (Sie können auch in eine anonyme Art projizieren könnte) ...

public class FruitViewModel 
{ 
    public FruitBase Fruit { get; set; } 
    public FruitnessFactor Factor { get; set; } 
} 

... und dann die Abfrage verwenden können:

List<FruitViewModel> fruitViewModels = context.FruitEntities 
    .OfType<Apple>() 
    .Select(a => new FruitViewModel 
    { 
     Fruit = a, 
     Factor = a.AppleFruitness 
    }) 
    .Concat(context.FruitEntities 
    .OfType<Orange>() 
    .Select(o => new FruitViewModel 
    { 
     Fruit = o, 
     Factor = o.OrangeFruitness 
    })) 
    .ToList(); 

Wenn Sie nicht tun deaktivieren Änderungsverfolgung (unter Verwendung AsNoTracking) die Navigationseigenschaften automatisch erhalten gefüllt, wenn die Einheiten an den Kontext gebunden bekommen („Relationship Fixup“), was bedeutet, dass Sie die Früchte aus dem Ansichtsmodell Sammlung extrahieren können ...

IEnumerable<FruitBase> fruits = fruitViewModels.Select(fv => fv.Fruit); 

... und Sie erhalten die Früchte einschließlich die FruitnessFactor Eigenschaften.

Dieser Code ist ziemlich umständlich, aber ein direkter Ansatz ohne eine Projektion hat mehrmals ohne Erfolg gefragt worden:

+0

Ich denke, ich gehe für die 2-Abfrage-Lösung. Ich fürchte nur eine Auswirkung auf die Leistung, wenn man berücksichtigt, dass ich sortieren, Seitenumbrüche und ähnliches machen muss. Aber bis jetzt sieht es gut aus. Prost! – Flo

Verwandte Themen