2010-05-25 13 views
6

Ok J'ai les configurations suivantes, je travaille bien. Ces lignes de code devraient faire une conversion de DAL Entity (Subsonic) vers un ViewModel. Je voudrais convertir cela en une déclaration LINQ à ligne unique et a proposé ce qui suit.Conversion de boucle à LINQ -

returnData.Options = this.ProductOptions.Select(o => o.ToDataModel()); 

et je reçois l'erreur suivante. Alors, pourquoi la première déclaration fonctionne-t-elle, mais pas le LINQ et quelles mesures puis-je prendre pour le résoudre?

Stack Trace

à System.Linq.Enumerable.First [TSource] (IEnumerable 1 source, Func 2 prédicat) à SubSonic.Extensions.Database.Load [T] (IDataReader rdr, point T, Liste 1 ColumnNames) at SubSonic.Extensions.Database.ToEnumerable[T](IDataReader rdr, List 1) ColumnNames à SubSonic.Linq.Structure.DbQueryProvider.Execute [T] (QueryCommand 1 query, Object[] paramValues) at lambda_method(Closure) at SubSonic.Linq.Structure.DbQueryProvider.Execute(Expression expression) at SubSonic.Linq.Structure.Query 1.GetEnumerator()

Peut-être est de faire avec subsonique?

+2

Quelle est la pile d'appel de l'exception? – SLaks

+0

Quel est le type de retour de ToDataModel()? –

+0

@Dave Swersky - Le type de retour est ProductOptionModel – LiamB

Répondre

7

Une possibilité est que cela ne fonctionne pas parce que vous avez modifié l'heure à laquelle la requête est matérialisée. Modifiez le code à ce lieu:

returnData.Options = this.ProductOptions.Select(o => o.ToDataModel()).ToList(); 

qui forcera la requête à évaluer en même temps qu'il était avant.

EDIT: Votre trace de pile montre First() étant appelée d'une façon ou d'une autre, mais nous n'avons rien à ce sujet dans le code que vous avez montré ... des idées où cela se produit?

EDIT: J'ai réalisé la différence - et je suis stupide de ne pas le faire avant. Vous voulez forcer la projection à faire en cours:

returnData.Options = this.ProductOptions 
         .AsEnumerable() 
         .Select(o => o.ToDataModel()) 
         .ToList(); 

Cet appel supplémentaire à AsEnumerable signifie qu'il sera la surcharge Enumerable.Select qui est appelée, ce qui en fait équivalent à votre code d'origine.

+0

@Jon SKeet - Merci pour la réponse. Ajout des résultats .ToList() int la même erreur. (Juste sur cette ligne maintenant plutôt que sur la vue) – LiamB

+0

@Jon Skeet - Sneeky soupçon que cela a à voir avec SubSonic. Comme je ne fais aucun appel à .First(); – LiamB

+0

@Pino: J'ai une autre idée. Modification maintenant ... –

0
this.ProductOptions.Select(o => o.ToDataModel()).ToList<ProductOptionModel>(); 
+0

Même problème lors de l'utilisation de la ligne d'exemple. – LiamB

-1

Je pense que vous devez vérifier la longueur de this.ProductOptions avant l'instruction LINQ.

Alors peut-être (révisé sans chèque null):

returnData.Options = (this.ProductOptions.Length > 0) ? this.ProductOptions.Select(o => o.ToDataModel()) : new List<ProductOptionModel>().AsEnumerable(); 
+0

Pourquoi la boucle fonctionne-t-elle alors? – LiamB

+0

Peut-être pas besoin de vérifier null. La boucle fonctionne car avec la longueur 0, le flux du programme n'entre jamais dans la boucle. –

+0

Sélectionnez ne devrait pas échouer si elle n'obtient aucune valeur si ... il devrait juste donner un résultat vide. –

2

Comme je l'ai dit que vous utilisez la méthode d'abord. vous voudrez peut-être le changer en FirstOrDefault. Ce sera résolu. ou pouvez-vous changer?

Stack Trace

à System.Linq.Enumerable.Premier

+0

comme je l'ai dit, je n'appelle pas directement cela. Cela semble être profond dans les fichiers subsoniques. Peut-être que cela cause le problème? – LiamB

+0

Oui. C'est pourquoi cela arrive. modifier. peut-être en utilisant try catch statements'll résoudre ce problème. as-tu essayé? – cem

+0

Voir Jon Skeets Réponse. – LiamB