2010-11-25 40 views
2

je l'ENUM et la classechaîne Parse Poco classe ENUM dans la requête LINQ MVC 2.0

public enum Gender 
{ 
    Male, 
    Female, 
    Unknown 
} 

public class Person 
{ 
    public int PersonId { get; set; } 
    public string LastName { get; set; } 
    public string FirstName { get; set; } 
    public Gender? Gender { get; set; } 
} 
POCO

suivant, je voudrais effectuer une requête « obtenir toutes les personnes » dans mon référentiel tel qu'il ressemblerait à quelque chose comme ceci:

return from p in _db.People 
     select new Model.Person 
     { 
      PersonId = p.PersonId, 
      LastName = p.LastName, 
      FirstName = p.FirstName, 
      Gender = p.Gender, 
     }; 

Malheureusement je reçois une erreur « Impossible de convertir implicitement le type « string » à « Model.Gender » »

je voudrais convertir la chaîne qui est en cours interrogé à partir du cadre d'entité à mon énumération de sexe et l'assigner à ma classe POCO.

Répondre

4

Les énumérations ne sont pas prises en charge dans Entity Framework. Il y a une solution de contournement par Alex James, mais c'est assez impliqué.

Au lieu de cela, je préfère le faire:

public enum Gender : byte 
{ 
    Male = 1, 
    Female, 
    Unknown 
} 

public class Person 
{ 
    public int PersonId { get; set; } 
    public string LastName { get; set; } 
    public string FirstName { get; set; } 
    public byte Gender { get; set; } // this is the EF model property 
    public Gender GenderType // this is an additional custom property 
    { 
     get { return (Gender) Gender; } 
     set { Gender = (byte)value; } 
    } 
} 

Il est essentiellement un crochet/enveloppe pour la valeur réelle. Dans votre base de données, stockez Sexe comme tinyint (qui correspond à byte sur le plan conceptuel).

Ensuite, vous pouvez utiliser un ENUM octet à la carte à et de la propriété modèle:

return from p in _db.People 
     select new Model.Person 
     { 
      PersonId = p.PersonId, 
      LastName = p.LastName, 
      FirstName = p.FirstName, 
      Gender = p.Gender, // sets byte 
     }; 

Mais si vous accédez à ce ViewModel, parce que votre réglage du champ d'octets pour Gender, vous aurez également accès à la propriété enum GenderType.

Est-ce que cela résout votre problème?

+0

Hey ça aide beaucoup. C'est dommage qu'il pollue le POCO mais cela devra faire pour le moment. Je n'avais pas beaucoup de chance avec la fausse solution ENUM à cause du modèle d'inversion de dépendance que j'utilise. Je suis désolé, je ne peux pas voter, vous répondez car je n'ai pas assez de rep. Merci beaucoup. – eNc

+0

Aucun problème, veuillez cocher l'une des réponses comme correcte (celui qui a résolu votre problème). Aussi, si vous ne voulez pas "polluer le POCO", vous pouvez le mettre dans une classe partielle, ou vous pouvez créer une méthode d'extension. Pourtant, rien de mal à avoir la propriété là-bas (je fais). Vous ne voulez pas que votre modèle de domaine devienne anémique. – RPM1984

0

essayer

Gender = p.Gender != null ? (Gender)Enum.Parse(typeof(Gender), p.Gender) : (Gender?)null; 

Pour analyser la chaîne comme l'un des énumérations

est ici une solution mais cela signifie changer votre POCO agréable et propre

http://blogs.msdn.com/b/alexj/archive/2009/06/05/tip-23-how-to-fake-enums-in-ef-4.aspx

+0

Je viens d'essayer cela, cependant, il ne fonctionne pas réellement dans la requête LINQ. L'utilisation de la méthode Enum.Parse est ce qui crée le problème. Une exception NotSupportedException se produit avec le message d'exception "LINQ to Entities ne reconnaît pas la méthode" System.Object Parse (System.Type, System.String) "et cette méthode ne peut pas être traduite dans une expression de magasin." – eNc

+0

Vous avez raison, j'ai édité la réponse avec une autre solution possible/solution de contournement – Jaime

+0

J'essaie de faire cette méthode de truquage d'enums. Est-il possible que vous pouvez aider avec une section. Je ne sais pas où créer ce "type complexe" on dirait que ça irait dans web.config mais je ne suis pas certain. – eNc

0
if (Enum.IsDefined(typeof(Gender), genderstring)) 
     Gender g = (Gender) Enum.Parse(typeof(Gender), genderstring, true); 
    else 
     //Deal with invalid string. 
+0

Cela me donne également une exception de type NotSupportedException avec le message d'erreur "LINQ to Entities ne reconnaît pas la méthode" System.Object Parse (System.Type, System.String) "méthode, et cette méthode ne peut pas être traduite dans une expression de magasin. " – eNc

1

Entity Framework que je connais ne prend pas en charge les énumérations. EF utilise votre expression de requête pour créer une instruction SQL qu'il envoie ensuite au serveur. S'il ne peut pas créer l'équivalent SQL d'une opération, il lève une exception NotSupportedException pour cette opération. Si vous prévoyez de renvoyer un petit jeu de données, vous pouvez le séparer de Entity Framework en créant un objet en mémoire à l'aide de la méthode ToArray.

var myEntities = (from entity in _db.Entities 
        where /* condition */ 
        select entity) 
         .ToArray(); 

Cela créera une séquence d'entités en mémoire.Toutes les autres déclarations de requête seront alors dans le domaine de LINQ aux objets qui permet l'analyse syntaxique des chaînes en énumérations:

return from myEntity in myEntities 
     select new MyDataContract 
     { 
      ID = myEntity.ID, 
      Gender g = (Gender)Enum.Parse(typeof(Gender), myEntity.Gender, true) 
     }; 

Ou vous pourriez même casser dehors dans une boucle foreach:

List<MyDataContract> myDataContracts = new List<MyDataContract>(); 
foreach (var myEntity in myEntities) 
{ 
    var dataContract = new MyDataContract { ID = myEntity.ID }; 

    if (Enum.IsDefined(typeof(Gender), myEntity.Gender)) 
     dataContract.Gender = (Gender)Enum.Parse(typeof(Gender), myEntity.Gender, true); 

     myDataContracts.Add(dataContract); 
} 

return myDataContracts.AsEnumerable();