2009-05-05 7 views
2

J'ai une requête linq qui renvoie l'ID d'une question en fonction du texte des questions. Cet ID doit ensuite être utilisé pour associer une date dans une table de dates à cette question particulière. La question est déjà enregistrée et la date est enregistrée à une heure différente. Le problème est que la requête retourne le questionID comme un type anonyme et donc quand j'ai besoin d'assigner ce questionID comme questionID dans une autre table, il jette une erreur, indiquant que la table attend un Guid. Suite à cela, j'ai converti le type anonyme en une chaîne et puis utilisé la fonctionnalité de conversion de GUID pour convertir la chaîne en un GUID, cependant il me donne maintenant l'erreur qu'un GUID devrait être 32 caractères et 4 tirets. Mes pensées à ce sujet sont que le type anonyme retourne le questionID en tant que "QuestionID = jkj939-89239829- etc etc." - Avec le préfixe des caractères au premier plan, et donc lors de la conversion en GUID, la chaîne convertie contient ces caractères.C# Linq Guid Anonyme Type Problème

Ai-je manqué quelque chose? Je ne peux vraiment pas comprendre pourquoi cela ferait, et y a-t-il un moyen de supprimer le préfixe retourné par le type anonyme? L'aide serait grandement appréciée.

Voici le code:

public static void GetQuesID(string quesText) 
    { 
     ExamineDataContext dc = new ExamineDataContext(); 
     var matchedques = from q in dc.GetTable<Question>() 
          where q.QuestionText.Contains(quesText) 
          select new{ 
           q.QuestionID 
          }; 
     foreach (var element in matchedques) 
     { 
      MessageBox.Show(element.ToString()); 
     } 

     try 
     { 
      Guid g = Guid.NewGuid(); 
      Table<DateLastUsed> dlused = Repository.GetDateLastUsedTable(); 
      DateLastUsed dlu = new DateLastUsed(); ; 
      string qidGuidString = matchedques.ToString(); 
      Guid convQuesGuid = new Guid(qidGuidString); 
      dlu.DLUID = g; 
      dlu.QuestionID = convQuesGuid; 
      dlu.DateLastUsed1 = DateTime.Now; 

      dlused.InsertOnSubmit(dlu); 
      dlused.Context.SubmitChanges(); 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 

Répondre

4

À moins que je ne manque quelque chose, pourquoi ne pas simplement select q.QuestionID au lieu de créer un nouveau wrapper de type anonyme?

var matchedques = from q in dc.GetTable<Question>() 
          where q.QuestionText.Contains(quesText) 
          select q.QuestionID; 

foreach (var element in matchedques) 
{ 
    MessageBox.Show(element.ToString()); 
} 

Vous pouvez également donner le champ un nom ("theID" ci-dessous) et d'y accéder directement:

var matchedques = from q in dc.GetTable<Question>() 
          where q.QuestionText.Contains(quesText) 
          select new{ 
           theID = q.QuestionID 
          }; 

foreach (var element in matchedques) 
{ 
    MessageBox.Show(element.theID.ToString()); 
} 

Apparemment, il y avait plus à la question que je pensais d'abord. En réponse au commentaire, gardez à l'esprit que vous renvoyez une énumération des résultats dans des correspondances (d'où le foreach ci-dessus, non?). Ainsi, la ligne suivante est aussi dans l'erreur:

string qidGuidString = matchedques.ToString(); 

Soit vous voulez

string qidGuidString = matchedques.Single().ToString(); 

si matchedques doivent contenir un seul résultat, ou une boucle foreach si matchedques doit contenir plusieurs résultats.


Notez qu'il n'y a aucune raison de convertir un GUID à chaîne et à nouveau, et vous pouvez également utiliser la requête pour renvoyer quelque chose de plus utile (à savoir, un nouvel objet DateLastUsed):

var matchedques = from q in dc.GetTable<Question>() 
          where q.QuestionText.Contains(quesText) 
          select new DateLastUsed() { 
           DLUID = Guid.NewGuid(), 
           QuestionID = q.QuestionID, 
           DateLastUsed1 = DateTime.Now 
          }; 

Table<DateLastUsed> dlused = Repository.GetDateLastUsedTable(); 

foreach(var dlu in matchedques) 
{ 
    dlused.InsertOnSubmit(dlu); 
    dlused.Context.SubmitChanges(); 
} 
+0

J'ai essayé, en changeant le code: dlu.QuestionID = correspondedques; REÇU ceci: Erreur: ne peut pas convertir implicitement le type 'System.Linq.IQueryable ' à 'System.Guid' \t C: \ Documents and – Goober

+0

J'ai effectué la réponse pour y remédier. –

+0

Bonjour, J'ai implémenté l'exemple de code que vous avez posté ci-dessus, et maintenant que le code se déclenche sans erreur comme avant, il n'insère pas de nouveaux détails. – Goober

1

Pourquoi ne pas seulement select q.QuestionID; au lieu de ce `nouveau sélectionner {q.QuestionID}; » des trucs?

+0

+1 Me battre jusqu'à 35 secondes. –

+0

J'ai essayé cela, en changeant le code à: dlu.QuestionID = matchedques; REÇU ceci: Erreur: Impossible de convertir implicitement le type 'System.Linq.IQueryable ' à \t C 'System.Guid': \ Documents and – Goober

+0

sahgilbert - voir ma réponse ci-dessous –

-1

Change to:

... 
var matchedques = from q in dc.GetTable<Question>() 
         where q.QuestionText.Contains(quesText) 
         select q.QuestionID; 

par exemple supprime le nouveau {...}, donc vous créez un nouveau type anonimouse avec la propriété id.

+0

Si vous votez contre, s'il vous plaît spécifier le raison. Quel problème avec cette réponse? – Kamarey

1

Vous appelez.ToString() sur matchedques, qui est une énumération:

var matchedques = from q in dc.GetTable<Question>() 
          where q.QuestionText.Contains(quesText) 
          select new{ 
           q.QuestionID 
          }; 

string qidGuidString = matchedques.ToString(); 

Donc, dans votre exemple ci-dessus, matchedques est un enunmeration des types anonymes (vous devriez probablement en finir avec cela et sélectionnez directement q.QuestionID). Appeler ToString() sur ceci retournera une représentation de chaîne de l'objet, et pas simplement l'QuestionId du premier élément de la séquence.

Vous vous attendez à ce qu'il n'y ait toujours qu'un seul résultat pour la requête ci-dessus? Si oui, vous devriez probablement regarder l'opérateur unique.

Quelque chose comme cela devrait faire:

var matchedQuesId = 
    dc.GetTable<Question>() 
    .Where(q =>q.QuestionText.Contains(quesText)) 
    .Single() 
    .QuestionID; 

Dans ce cas, vous pouvez alors utiliser matchedQuesId directement. Notez que si la requête Where correspond à none, ou à plus d'un élément, une erreur sera générée. Lisez sur l'opérateur unique pour savoir pourquoi.

1

Essayez ceci:

var matchedques = (from q in dc.GetTable<Question>() 
        where q.QuestionText.Contains(quesText) 
        select new{ 
         q.QuestionID 
        }).FirstOrDefault(); 

Ensuite, il suffit:

if (matchedques != null){ 
    // Just use matchedques.QuestionID to get your value 
} 

FirstOrDefault va définir le matchedques var à une seule instance de l'objet, pas une ennumeration d'entre eux. Fonctionne un régal quand vous savez qu'il y a juste une valeur que vous voulez. Le bit OrDefault signifie que ce sera NULL si rien n'est trouvé.

Questions connexes