Cast() exception: LINQ to entities seulement prend en charge la conversion EDM primitive ou une énumération des types de
Je veux afficher une entité nommée CriminalEvent
dans un but MVC vue que j'ai écrit. La vision exige que le Modèle de passer, il doit mettre en œuvre le IDataModel
interface. Maintenant, CriminalEvent
a les propriétés d'implémenter cette interface, mais sous un autre nom et je ne peux pas le changer.
Donc, dans mon code j'ai hérité de CriminalEvent
et ma classe dérivée (également appelé CriminalEvent, stupide, je suppose, mais me permet d'éviter de nombreux changements de code...) explicite le code de l'interface:
Using ViewApp;
public interface IDataModel
{
int ID { get; set; }
int CriminalEventID { get; set; }
}
public class ViewCriminalEvent : AIM.Police.DB.CriminalEvent, IDataModel
{
int IDataModel.ID
{
get { return CriminalEventID; }
set { CriminalEventID = value; }
}
}
(Je sais, dans ce cas, l'interface de la propriété ID est égal à CriminalEventID, c'est Ok)
Je m'attendais à être en mesure de lire les AIM.Police.DB.CriminalEvent
Entités et remplir mon point de vue, le modèle par Linq to entities Cast()ing à la dérivée CriminalEvent
, comme ceci:
Le modèle de vue (j'en ai besoin pour remplir le CriminalEvents
la propriété):
Using ViewApp;
public class CriminalEventMainViewModel
{
public IEnumerable<IDataModel> CriminalEvents { get; set; }
public IDataModel SelectedEntity { get; set; }
public string SubEntityDisplayName { get; set; }
public IEnumerable<IDataModel> SubEntityCollection { get; set; }
public IDataModel SelectedSubEntity { get; set; }
}
et le code du Contrôleur:
Using ViewApp;
private ViewResult CriminalEventIndexView(CriminalEvent selectedCriminalEvent = null)
{
CriminalEventMainViewModel viewModel =
new CriminalEventMainViewModel();
using (var db1 = new AIM.Police.DB.InvestigationContext(lazyLoadingEnabled: false))
{
viewModel.CriminalEvents = db1.CriminalEvents.Cast<ViewCriminalEvent>().ToList(); //THIS LINE THROWS THE EXCEPTION
viewModel.SelectedEntity = selectedCriminalEvent;
}
return View("Index", (object)viewModel);
}
Note à la fois l'original CriminalEvent
classe et la InvestigationContext
sont trouvés dans le BUT.La Police.DB dll que je ne peux toucher
L'Erreur:
Unable to cast the type 'AIM.Police.DB.CriminalEvent' to type 'InvestigationSimulator.Models.CriminalEvent'. LINQ to Entities only supports casting EDM primitive or enumeration types.
Pourquoi j'ai cette erreur?
Remarques sur ma façon de faire sont toujours les bienvenus..
Vous devez vous connecter pour publier un commentaire.
Puisque vous êtes l'obtention de l'ensemble des entités, vous pourrait se concrétiser d'abord la requête, puis effectuer la distribution.
Cela permettrait d'effectuer la distribution en mémoire au lieu d'essayer de la formuler dans le cadre de la requête de traduction. L'erreur vient de ce que LINQ to entities ne prend pas en charge la transformation du SQL à une non-entité de la classe, même lorsqu'il hérite d'une classe d'entité, car il n'existe pas de cartographie pour les colonnes supplémentaires à la
SELECT
déclaration. En matérialisant les données, puis la mise àCast
dans la mémoire (LINQ to Objects), vous évitez l'erreur de traduction.Cependant, dans votre cas, vous avez l'héritage vers l'arrière pour que cela fonctionne. Pour que cela fonctionne, je vous conseille d'avoir la DB modèle à mettre en œuvre
IDataModel
et d'éviter la fonte entièrement, voir http://msdn.microsoft.com/en-us/library/vstudio/bb738696(v=vs. 100).aspx et http://msdn.microsoft.com/en-us/library/wa80x488.aspx. En particulier, vos partielle de la classe peut implémenter l'interface (ne sais pas si le concepteur vous permet d'ajouter une définition de l'interface, puisque je n'en code-première de ces jours). Notez que ceci peut éliminer le besoin pour votre modèle spécifique à la vue entièrement.L'alternative, ce qui m'aiderait sans doute à faire, c'est de garder le modèle de vue complètement distinct (pas hériter de la classe d'entité) et l'utilisation AutoMapper à la carte entre eux.
InvalidCastException
?AIM.Police.DB.CriminalEvent
ne découle pas d'InvestigationSimulator.Models.CriminalEvent
. La question n'est pas claire (deuxCriminalEvent
classes dans les différents espaces de noms, et le code à l'aide de références non qualifiés, sans montrer lausing
espaces de noms), mais je pense que EF sera configuré pour le retourAIM.Police.DB.CriminalEvent
, et dans ce cas, il juste ne fonctionnera pas.Using
le modèle de vue de l'espace de noms et ainsi est toute mention deCriminalEvent
(sauf si explicitement indiquéAIM.Police.DB
). Je vais mettre à jour le code ci-dessus...IIdentifiable
je suppose)Enumerable.Cast<TResult>
est en train de jeter chaque élément de la collection. Et il échoue dans votre scénario (pas de surprise) parce que vous êtes en train de jeter les instances de parent (AIM.Police.DB.CriminalEvent
) classe d'objets de enfant (InvestigationSimulator.Models.CriminalEvent
) de la classe. Vous ne pouvez pas faire ce genre de casting en C#.Pour corriger cela, vous aurez besoin de charger des objets de votre base de données et puis les convertir (map) - les manuellement votre Modèle de classe. La plus simple est de code comme ceci:
ToList().Select(...)
essentiellement inutilement crée une liste pour une simple énumération. Il devrait probablement êtreToList().ConvertAll(...)
ouAsEnumerable().Select(...)
. (Le résultat de l'ensemble des trois sera le même que la manière dont ils sont arrivés à ce résultat diffère.)Id
prop dans votre plus Simple Code à titre d'exemple et doit être fait pour toutes les propriétés de parent?Utiliser cast après ToList() ou Unique (en)
_c.Customers.ToList<CustomerBinding>()