Trasmissione a un tipo derivato in una query LINQ to Entities con ereditarietà Tabella per gerarchia

Dispongo di un modello LINQ per quadro con ereditarietà Tabella per gerarchia. Ho una query sul tipo di base e voglio fare una logica dipendente dal tipo specifico. Per esempio:

IQueryable base = ... // this works fine var result = base.Select(b => b is DerivedType1 ? 1 : 2).ToList(); // this doesn't compile to SQL var result2 = base.Select(b => b is DerivedType1 ? ((DerivedType1)b).DerivedProperty : null).ToList(); 

C’è un modo per fare qualcosa di simile senza elaborare IQueryables di ogni tipo derivato separatamente:

 // I'd rather not do this: var resultA = base.OfType().Select(d => d.DerivedProperty); var resultB = base.OfType().Select(d => default(int?)); var result = resultA.Concat(resultB).ToList(); 

La trasmissione diretta a un tipo di entity framework come (DerivedType1)b non è supportata con LINQ-to-Entities ma l’operatore as ( b as DerivedType1 ) è, quindi è ansible provare:

 var result2 = base .Select(b => b is DerivedType1 ? (b as DerivedType1).DerivedProperty : null) .ToList(); 

Si potrebbe avere un metodo sul proprio tipo di base sovrascritto nei tipi derivati ​​per fornire il valore della proprietà pertinente.

 public class MyBaseClass { public virtual int GetSomething() { throw new NotImplementedException(); } } public class MyDerivedClass1 : MyBaseClass { public int SomeProperty { get; set; } public override int GetSomething() { return this.SomeProperty; } } public class MyDerivedClass2 : MyBaseClass { public int SomeOtherProperty { get; set; } public override int GetSomething() { return this.SomeOtherProperty; } } 

Quindi potresti:

 var result = base.Select(b => b.GetSomething()).ToList(); 

Prova questo, non ho mai fatto nulla con la necessità di fare questo tipo di questo, ma questo dovrebbe farlo. Inoltre, se si utilizza la base , innanzitutto non lo fanno perché è una parola chiave, ma se è necessario, utilizzare @base @ davanti al nome indica che non è utilizzato come parola chiave.

 var resultA = base.Select(aVar => (aVar is DerivedType1) ? (DerivedType)(((DerivedType1)aVar).DerivedProperty) : (DerivedType)(default(int?)) ).ToList(); 
 OfType() 

restituirà un object IEnumerable, se ansible, prova a passare a tipo-base in IEnumerable anziché IQueryable; potresti utilizzare alcune restrizioni SQL quando usi IQueryable.

Questo è, ovviamente, se non si sta effettivamente interrogando un database?

È ansible utilizzare EntityFramework.Extended per migliorare le prestazioni della query anziché eseguire 2 round trip su DB.

 var resultA = base.OfType().Select(d => d.DerivedProperty).Future(); var resultB = base.OfType().Select(d => default(int?)).Future(); var result = resultA.Concat(resultB).ToList(); 

In questo caso viene eseguito solo un round trip su bd. Questo framework è molto utile per molte altre cose su EF