2016-12-29 3 views
3

Obtention d'une erreur lors de l'exécution de la version F # du code ci-dessous alors que la version C# ci-dessous fonctionne. Des idées sur la façon de retourner plusieurs propriétés documentdb à partir d'une requête linq avec F # en général?Comment utiliser DocumentDb, LINQ et F # pour renvoyer plusieurs propriétés?

2016-12-29T23:57:08.504 Exception while executing function: Functions.GetTags. mscorlib: Exception has been thrown by the target of an invocation. mscorlib: One or more errors occurred. Microsoft.Azure.Documents.Client: Constructor invocation is not supported.  

C#

var userTagsQuery = 
    userDocument.Where(user => user.topics != null && user.education != null) 
    .Select(user => new {topics=user.topics, education=user.education}); 

F #

type UserTagRecord = {topics : string list; education : string list} 
    let userTagsQuery = 
    user.Where(fun user -> user.topics <> null && user.education <> null) 
    .Select(fun user -> {topics=user.topics :?> string list; education=user.education :?> string list}) 
+0

Je n'ai rien fait avec documentDB, mais peut-être que la dynamique peut vous aider un peu? 'FSharp.Interop.Dynamic' et' System.Linq.Dynamic'. Encore une fois, peut-être pas ... – s952163

Répondre

2

L'erreur dit "invocation Constructor est pas pris en charge". C'est une limitation raisonnable, la plupart des fournisseurs LINQ l'ont.

Dans votre code F #, l'appel du constructeur est la création de l'enregistrement. Les enregistrements F # sont compilés en tant que classes avec un ensemble de propriétés en lecture seule et un seul constructeur qui prend les valeurs de ces propriétés en tant que paramètres. Selon le message d'erreur, l'appel de ce constructeur n'est pas pris en charge. Malchance. Une chose intéressante à noter est que les types anonymes C# (employés dans votre code C#) fonctionnent exactement de la même manière que les enregistrements F # - ce sont des classes avec un tas de propriétés en lecture seule et un seul constructeur, - et pourtant, ils sont soutenus. La gestion des types anonymes C# en tant que cas particulier est, encore une fois, une pratique courante pour les fournisseurs LINQ. Beaucoup de fournisseurs de LINQ géreraient cela de manière plus générale, ce qui couvrirait aussi les enregistrements F #, mais dans ce cas, ce n'est apparemment pas le cas. Si j'étais vous, j'ouvrirais un problème à ce sujet.

Ce que vous pouvez essayer est de remplacer votre dossier avec une classe avec des propriétés mutables et construire avec la syntaxe d'initialisation de la propriété:

type UserTagRecord() = 
    member val topics : string list = [] with get, set 
    member val education : string list = [] with get, set 

let userTagsQuery = 
    user 
     .Where(fun user -> user.topics <> null && user.education <> null) 
     .Select(fun user -> UserTagRecord(topics=user.topics :?> string list, education=user.education :?> string list)) 

Je voudrais aussi aller sur une branche ici et suggère que vous pourriez avoir plus problème avec l'utilisation des listes F #. Premièrement, DocumentDb pourrait ne pas les aimer par eux-mêmes, et deuxièmement, je ne sais pas ce que sont user.topics et user.education, mais je suis assez sûr qu'ils ne sont pas une sous-classe de string list, donc vos lancements échoueront probablement.

+1

Merci pour la réponse Fyodor, il est instructif sur les enregistrements F # ainsi que utile pour le dépannage du problème. J'ai annoté ma classe User avec l'attribut [] car les propriétés topic et education peuvent être nulles. J'initialise ces propriétés à null. Cela me permet de filtrer en fonction de user.topics <> null && user.education <> null car la liste de chaînes ne supporte pas null. Je suis ensuite tombé de obj à la liste de chaînes. Implémentation de votre solution avec un UserTagRecord simplifié avec uniquement des rubriques et suppression de la clause Where et des exigences de conversion associées –

+0

Je reçois une erreur nouvelle et différente 2016-12-30T01: 46: 11.710 Exception lors de l'exécution de la fonction: Functions.GetTags. mscorlib: Une exception a été émise par la cible d'une invocation. FSharp.Core: Impossible de convertir la citation F # suivante en un arbre d'expression LINQ -------- Sequential (Sequential (Value (), PropertySet (Some (returnVal), rubriques, [PropertyGet (certaines (user), topics, [])])), returnVal) –

+0

Permettez-moi de préciser que l'attribut [] est utilisé pour contourner cette erreur. Le type 'liste de chaînes' n'a pas 'null' comme valeur correcte lors de l'utilisation de la clause Where –