2008-10-02 7 views
5

Je rencontre certaines particularités avec LINQ to SQL.LINQ to SQL Particularités

Avec une requête relativement simple, je veux sélectionner certains domaines, mais ont les champs de date formatées sous forme de chaînes, dont je suis OBTENUS comme ceci:

 var list = dataContext.MyLists.Single(x => x.ID == myId); 

     var items = from i in list.MyItems 
        select 
         new 
          { 
           i.ID, 
           i.Sector, 
           i.Description, 
           CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "", 
           DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : "" 
          };        

Plus tard j'ai essayé la requête suivante, qui est exactement la même chose, sauf que je suis tout droit de mon interrogation datacontext, plutôt que d'un élément dans ma première requête:

 var items = from i in dataContext.MyLists 
        select 
         new 
          { 
           i.ID, 
           i.Sector, 
           i.Description, 
           CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "", 
           DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : "" 
          }; 

le premier fonctionne très bien, mais la seconde requête donne un:

Impossible de traduire l'expression '...' en SQL et n'a pas pu la traiter comme une expression locale.

Si je supprime les lignes qui Formatent la date, cela fonctionne très bien. Si je supprime la vérification .HasValue cela fonctionne également bien, jusqu'à ce qu'il y ait des valeurs nulles.

Des idées?

Anthony

+0

Semble vous avez deux questions totalement différentes. On sélectionne à partir de MyItems dans un objet MyList. Le second est la sélection à partir des objets MyList (pas MyItems). Les types de données sont-ils les mêmes pour les deux? Il est assez difficile de déboguer ceci sans savoir quelles sont les structures de la table. – Bryant

Répondre

14

Je ferais la partie SQL sans faire la mise en forme, puis le formatage du côté client:

var items = list.MyItems.Select(item => new { item.ID, item.Sector, item.Description, 
               item.CompleteDate, item.DueDate }) 
         .AsEnumerable() // Don't do the next bit in the DB 
         .Select(item => new { item.ID, item.Sector, item.Description, 
               CompleteDate = FormatDate(CompleteDate), 
               DueDate = FormatDate(DueDate) }); 


static string FormatDate(DateTime? date) 
{ 
    return date.HasValue ? date.Value.ToShortDateString() : "" 
} 
+0

Ooooh J'ai aimé que .AsEnumerable() se divise là-dedans. Agréable. – Lucas

+0

Enregistré par SO encore une fois ... merci !! –

+0

@Jon Skeet - Je t'aime. –

8

Dans la première requête, vous avez déjà les données de retour de la base de données au moment où la deuxième ligne court (éléments var = ...). Cela signifie que la deuxième ligne s'exécute sur le client, où ToShortDateString peut fonctionner assez bien. Dans la deuxième requête, parce que la sélection s'exécute directement sur une collection IQueryable (dataContext.MyLists), elle tente de traduire la sélection en SQL pour traitement sur le serveur, où ToShortDateString n'est pas compris, d'où le message "Could Not Translate". .. "exception. Pour comprendre un peu mieux cela, vous devez vraiment comprendre la différence entre IQueryable et IEnumerable, et à quel point une requête Linq To Sql cesse d'être IQueryable et devient IEnumerable. Il y a beaucoup de choses sur le web à ce sujet.

Hope this helps,

Paul

6

Tout comme le message d'erreur vous dit, la différence est due à ce qui peut être fait localement à distance lors de la connexion à SQL.

Le code Linq doit être converti par Linq en SQL en une commande SQL pour les données distantes - tout ce qui doit être fait localement ne peut pas être inclus. Une fois que vous l'avez tiré dans un objet local (dans le premier exemple), il n'utilise plus Linq to SQL, mais simplement Linq. À ce stade, vous êtes libre de faire des manipulations locales.

2

Peut-être qu'il y avait une erreur de copier-coller ou juste une faute de frappe dans votre échantillon. Mais sinon, cela pourrait être le problème ...

Dans la deuxième requête vous interrogez une collection de listes, alors que dans la première requête vous interrogiez les éléments dans une liste. Mais vous n'avez pas ajusté la requête pour tenir compte de cette différence.

Ce dont vous avez besoin pourrait être ceci. Notez les lignes commentées qui n'apparaissent pas dans votre deuxième échantillon.

var items = from aList in dataContext.MyLists 
       from i in aList.MyItems // Access the items in a list 
       where aList.ID == myId // Use only the single desired list 
       select 
        new 
         { 
          i.ID, 
          i.Sector, 
          i.Description, 
          CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "", 
          DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : "" 
         };