Transtypage en un type dérivé dans une requête LINQ to Entities avec un inheritance Table par hiérarchie

J’ai un modèle LINQ to entity avec l’inheritance Table Per Hierarchy. J’ai une requête sur le type de base et je souhaite effectuer une logique spécifique dépendante du type. Par exemple:

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

Existe-t-il un moyen de procéder de cette manière sans traiter séparément IQueryables de chaque type dérivé:

 // 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 diffusion directe vers un type d’entité tel que (DerivedType1)b n’est pas prise en charge par LINQ-to-Entities, mais l’opérateur as ( b as DerivedType1 ), vous pouvez donc essayer:

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

Vous pouvez avoir une méthode sur votre type de base qui est remplacée dans vos types dérivés pour fournir la valeur de propriété 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; } } 

Ensuite, vous pourriez:

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

Essayez ceci, je n’ai jamais rien fait d’avoir besoin de faire ce genre de chose mais cela devrait le faire. De même, si vous utilisez base , ne le faites pas d’abord parce qu’il s’agit d’un mot clé, mais si vous devez le faire, utilisez @base le @ devant le nom indique qu’il n’est pas utilisé en tant que mot clé.

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

retournera un IEnumerable, si possible, essayez de passer du type de base à IEnumerable au lieu de IQueryable, vous pouvez vous conformer à certaines ressortingctions SQL lorsque vous utilisez IQueryable.

C’est bien sûr si vous n’exécutez pas réellement une firebase database?

Vous pouvez utiliser EntityFramework.Extended pour améliorer les performances de la requête au lieu d’effectuer 2 allers-retours vers la firebase database.

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

Dans ce cas, un seul voyage aller-retour vers BD est exécuté. Ce cadre est très utile pour beaucoup d’autres choses int EF