2010-11-05 4 views
3

J'essaie désespérément de créer une "IN CLause" via f # linq - mais je n'arrive pas à l'obtenir. J'ai essayé deux options:FLinq SQL "IN Clause"

itérez la liste des jours dans le cadre de l'expression de la séquence:

let getHistoricalQuotes (securityId:int) (days:string seq) = 
    let results = 
     Query.query <@ seq { 
      for day in days do 
       for sq in db.SecurityQuote do 
        if sq.SecurityId =?! securityId && sq.Day = day then 
         yield sq ; 
     } @> 

Et une clause List.exists:

let getHistoricalQuotes (securityId:int) (days:string list) = 
    let results = 
     Query.query <@ seq { 
      for sq in db.SecurityQuote do 
       if sq.SecurityId =?! securityId && List.exists (fun d -> d = sq.Day) days then 
        yield sq ; 
     } @> 

    results 

Les deux me donnent:

base {System.SystemException} = {"Méthode 'Microsoft.FSharp.Cor e.FSharpFunc 2[System.String,System.Boolean] ToFSharpFunc[String,Boolean](System.Converter 2 [System.String, System.Boolean]) » n'a pas de traduction pris en charge SQL."}

comme toujours, merci pour l'aide à l'avance ...


à réécrit:

let getHistoricalQuotes (securityId:int) (days:string list) = 
    let results = 
     Query.query <@ 
      Query.join 
       db.SecurityQuote 
       days 
       (fun sq -> if(sq.SecurityId =?! securityId) then sq.Day else "") 
       (fun d -> d) 
       (fun sq d -> sq) @> 

    results 

et a obtenu ce excepion:

System.Exception was unsledled
Message = La construction suivante était utilisée dans la requête mais non reconnue par le traducteur de requête F # -to-LINQ: Valeur (["2010/01/04"; "2010/02/01"; "2010/03/01"; "2010/04/01"; "2010/05/03"; "2010/06/01"; "2010/07/01"; "2010/08/02"; "2010/09/01"; "2010/10/01"; "2010/11/01"; "2010/12/01"; "2010/01/29"; "2010/02/26"; "2010/03/31"; "2010/04/30"; "2010/05/31"; "2010/06/30"; "2010/07/30"; "2010/08/31"; "2010/09/30"; "2010/10/29"; "2010/11/30"; "2010/12/31"]) Ceci est pas une expression de requête valide. Vérifiez la spécification des requêtes autorisées et envisager de déplacer une partie de la requête de la citation

et la suppression des citations n'a pas causé une erreur - mais il a généré une requête incroyablement incorrecte (selext * de historicalquote)


Tricher pour l'instant, jusqu'à ce que je peux revenir et corriger le problème - mais au moins je peux garder la signature même, bien que je vais thrashing la base de données.

let getHistoricalQuotes (securityId:int) (days:string list) = 
    let getQuote (day) = 
     Query.query <@ seq { 
      for sq in db.SecurityQuote do 
       if sq.SecurityId =?! securityId && sq.Day = day then 
        yield sq ; 
     } @> |> Seq.head 

    List.map (fun day -> getQuote day) days 

par Will ci-dessous j'ai essayé ce

let getHistoricalQuotes (securityId:int) (days:string list) = 
    let results = 
     Query.query <@ seq { 
      for sq in db.SecurityQuote do 
       if sq.SecurityId =?! securityId && days.Contains(sq.Day) then 
        yield sq ; 
     } @> 
    results 

Mais il ne compile pas

Erreur 1 Le champ, constructeur ou membre 'contient' est pas défini


Enfin - (Merci vous):

let getHistoricalQuotes (securityId:int) (days:string array) = 
    let results = 
     Query.query <@ seq { 
      for sq in db.SecurityQuote do 
       if sq.SecurityId =?! securityId && days.Contains(sq.Day) then 
        yield sq ; 
     } @> 
    results 

Et oui - vous devez ouvrir System.Linq - ces méthodes sont d'extension ou à elast partiellement - ils doivent être,

+0

Je viens de lire quelque part que F # ne pourrait pas soutenir la consommation des méthodes d'extension ... Je suis à la recherche d'une alternative ... http://stackoverflow.com/questions/777247/using-extension-methods-defined-in-c-from-f-code – Will

+0

Essayez System.Linq.Enumerable.Contains (jours, jours) .. en supposant que F # prenne en charge la consommation de méthodes génériques. – Will

+0

Heureux d'avoir aidé, et bien pour voir que F # supporte les extensions - c'est un bon sucre syntaxique. Avec 'open System.Linq' en place, vérifiez les autres méthodes qui se trouvent sur n'importe quel objet IEnumerable - il y a beaucoup à jouer avec, et la plupart fonctionnent avec EF. Cheers – Will

Répondre

2

Il existe déjà dans Linq, mais le contraire de ce que vous êtes à l'utilisation:

days.Contains(day) 
+0

Il ne compile pas pour moi. 'Contient' n'est pas défini. Je dois le mettre au mauvais endroit. Je suis en train d'éditer ci-dessus ... – akaphenom

+0

Je suis un développeur C#, et je peux à peine lire F #, mais Contains fait partie du framework .Net et devrait donc fonctionner dans toutes les langues. J'écris normalement un code similaire à ceci: 'var validValues ​​= new [] {1,2,3}; var résultat = source.Where (item => validValues.Contains (item.Property1)); 'J'espère que vous pouvez lire C# et traduire ... – Will

+0

Je suppose que vous importez/utilisez System.Linq? (ou quelle que soit la déclaration équivalente en F #) – Will