I am trying haplessly to create an "IN CLause" through f# linq - but can't seem to get it. I have tried two options:
Iterating over the list of days as part of the sequence expression:
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 ;
} @>
And a List.exists clause:
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
Both are giving me:
base {System.SystemException} = {"Method 'Microsoft.FSharp.Core.FSharpFunc
2[System.String,System.Boolean] ToFSharpFunc[String,Boolean](System.Converter
2[System.String,System.Boolean])' has no supported translation to SQL."}
as always, thanks for the help in advance...
rewrote to:
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
and got this excepion:
System.Exception was unhandled
Message=The following construct was used in query but is not recognised by the F#-to-LINQ query translator: Value (["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"]) This is not a valid query expression. Check the specification of permitted queries and consider moving some of the query out of the quotation
and removing the quotations didn't cause an error - but it generated a incredibly incorrect query (selext * from historicalquote)
Cheating for now, until I can come back and fix the problem - but at least I can keep the signature the same, though I will be thrashing the database.
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
Per Will below i tried this
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
But it doesn't compile
Error 1 The field, constructor or member 'Contains' is not defined
Finally - (Thank you will):
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
And yes - you need to open System.Linq - Are those extension methods, or at elast partially - they must be,