2008-09-26 7 views
3

je un suivant SQL Server schéma de base de données 2005:projection entité Nullable dans Entity Framework

CREATE TABLE Messages (
    MessageID int, 
    Subject varchar(500), 
    Text varchar(max) NULL, 
    UserID NULL 
) 

La colonne "UserID" - qui peut être nulle - est une clé étrangère et des liens vers la table

CREATE TABLE Users (
    UserID int, 
    ... 
) 

maintenant, j'ai plusieurs classes POCO avec des noms des messages, etc. utilisateur que j'utilise dans la requête suivante:

public IList<Message> GetMessages(...) { 
    var q = (from m in dataContext.Messages.Include("User") 
      where ... 
      select m); // could call ToList(), but... 

    return (from m in q 
      select new Message { 
      ID = m.MessageID, 
      User = new User { 
       ID = m.User.UserID, 
       FirstName = m.User.FirstName, 
       ... 
      } 
      }).ToList(); 
} 

Notez maintenant que je conseille le framework d'entité - en utilisant Include ("Users") - pour charger un utilisateur associé à un message, le cas échéant. Notez également que je n'appelle pas ToList() après la première instruction LINQ. Ce faisant, seules les colonnes spécifiées dans la liste de projection - dans ce cas, MessageID, UserID, FirstName - seront renvoyées à partir de la base de données.

Voici le problème - dès que Entity Framework rencontre un message avec UserID == NULL, il lève une exception, disant qu'il ne pouvait pas convertir en Int32 parce que la valeur DB est NULL.

Si je change les deux dernières lignes

return (from m in q 
     select new Message { 
      ID = m.MessageID, 
      User = m.User == null ? null : new User { 
       ID = m.User.UserID, 
       ... 
      } 
     }).ToList() 

puis une exécution NotSupportedException est jeté dire qu'il ne peut pas créer un type d'utilisateur constante et primitives seulement comme int, string, guid sont pris en charge .

Quelqu'un a-t-il une idée de la façon de le gérer en plus de matérialiser les résultats juste après la première instruction et d'utiliser ensuite la projection en mémoire? Merci.

+0

Le type de message que vous projetez diffère-t-il du type de m? Pourquoi projetez-vous du tout? –

+0

Pourquoi construisez-vous de nouveaux objets Message et Utilisateur plutôt que d'utiliser ceux que vous avez récupérés à partir de q? Je pense que vous n'utilisez pas bien le cadre. –

+0

@ DavidB: Message est un POCO, m est une classe Entity. @ Orion Adrian: Eh bien, je veux être en mesure de mettre en cache les résultats de la requête plus tard. Avec les objets d'entité, vous devez les détacher manuellement (y compris tous les objets dépendants, par ex. Utilisateur dans ce cas, ce qui est beaucoup trop de tracas (LINQ2SQL a le même problème). –

Répondre

0

je soupçonne que votre relation n'est pas 1 à 1.

+0

A droite, c'est une relation 1: n, un message appartient à seulement 1 utilisateur, mais un utilisateur peut avoir plusieurs messages. –

+0

Que fait la propriété m.Users? J'ai supposé que c'était un groupe d'utilisateur associé au message. – leppie

+0

OK, m.Users devrait effectivement être m.User, je l'ai changé dans la question originale. Cette propriété est une entité pointant vers l'utilisateur qui a envoyé ce message. –

0

Depuis que vous avez fait un .Include("Users") vous devriez être en mesure de traverser juste la User propriété de l'objet Message pour obtenir les informations de votre besoin.

+0

Oui, c'est comme cela que je le fais, sauf quand aucun utilisateur n'est associé au message (rappelez-vous, UserID est nullable). –

+0

S'il n'y a pas d'objet utilisateur, vous voudriez une valeur nulle. Que cherchez-vous plutôt? –

2

Vous avez oublié d'inclure la déclaration de votre classe "Message" mais je soupçonne que la propriété UserID dans cette classe n'est pas déclarée comme un type Nullable. Si c'est le cas, changez le "int" en "int?" (nullable int).

+1

Je pense que cette discussion sur les forums MS s'applique également. Cela fait probablement la même chose que ce que cette réponse suggère. http://social.msdn.microsoft.com/forums/fr-FR/adodotnetentityframework/thread/d206f59c-2ccc-4c93-917d-0bcbd40dfa1b/ – villecoder