2 people like it.

In-list / contains expression

Filter by list of properties when provider supports filter expressions but doesn't support Contains. Equivalent C# : https://gist.github.com/mausch/6893533

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
#r "System.Data.Services.Client"
#r "FSharp.Data.TypeProviders"

type nuget = Microsoft.FSharp.Data.TypeProviders.ODataService<"https://nuget.org/api/v2">
type Package = nuget.ServiceTypes.V2FeedPackage
let ctx = nuget.GetDataContext()

let packagesId = ["FSharpx.Http"; "FSharpx.Core"]

open System.Linq

let packages_throws_error() = // throws System.NotSupportedException: The method 'Contains' is not supported.
    query {
        for p in ctx.Packages do
        where ((packagesId.Contains(p.Id)) && p.IsAbsoluteLatestVersion && p.IsLatestVersion)
        select p
    }
    |> Seq.toList

// We implement it by folding ORs:

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns

let inList (membr: Expr<'a -> 'b>) (values: 'b list) : Expr<'a -> bool> =
    match membr with
    | Lambda (_, PropertyGet _) -> 
        match values with
        | [] -> <@ fun _ -> true @>
        | _ -> values |> Seq.map (fun v -> <@ fun a -> (%membr) a = v @>) |> Seq.reduce (fun a b -> <@ fun x -> (%a) x || (%b) x @>)
    | _ -> failwith "Expression has to be a member"

let packages = 
    query {
        for p in ctx.Packages do
        where (((%(inList <@ fun (x: Package) -> x.Id @> packagesId)) p) && p.IsAbsoluteLatestVersion && p.IsLatestVersion)
        select p
    }
    |> Seq.toList
type nuget =
  static member GetDataContext : unit -> V2FeedContext + 1 overload
  nested type ServiceTypes

Full name: Script.nuget


<summary>Provides the types to access an OData service</summary><param name="ServiceUri">The Uri for the OData service</param><param name='LocalSchemaFile'>The local .csdl file for the service schema</param><param name='ForceUpdate'>Require that a direct connection to the service be available at design-time and force the refresh of the local schema file (default: true)</param><param name='ResolutionFolder'>The folder used to resolve relative file paths at compile-time (default: folder containing the project or script)</param><param name='DataServiceCollection'>Generate collections derived from DataServiceCollection (default: false)</param>
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Data
namespace Microsoft.FSharp.Data.TypeProviders
type ODataService

Full name: Microsoft.FSharp.Data.TypeProviders.ODataService


<summary>Provides the types to access an OData service</summary><param name="ServiceUri">The Uri for the OData service</param><param name='LocalSchemaFile'>The local .csdl file for the service schema</param><param name='ForceUpdate'>Require that a direct connection to the service be available at design-time and force the refresh of the local schema file (default: true)</param><param name='ResolutionFolder'>The folder used to resolve relative file paths at compile-time (default: folder containing the project or script)</param><param name='DataServiceCollection'>Generate collections derived from DataServiceCollection (default: false)</param>
type Package = nuget.ServiceTypes.V2FeedPackage

Full name: Script.Package
type ServiceTypes =
  nested type SimpleDataContextTypes
  nested type V2FeedContext
  nested type V2FeedPackage

Full name: Script.nuget.ServiceTypes


<summary><para>The full API to the OData Service.</para><para>To use the service via the full API, create an instance of one of the types 'V2FeedContext'.</para><para>You may need to set the Credentials property on the instance.</para></summary>
type V2FeedPackage =
  new : unit -> V2FeedPackage
  member Authors : string with get, set
  member Copyright : string with get, set
  member Created : DateTime with get, set
  member Dependencies : string with get, set
  member Description : string with get, set
  member DownloadCount : int with get, set
  member GalleryDetailsUrl : string with get, set
  member IconUrl : string with get, set
  member Id : string with get, set
  ...

Full name: Script.nuget.ServiceTypes.V2FeedPackage
val ctx : nuget.ServiceTypes.SimpleDataContextTypes.V2FeedContext

Full name: Script.ctx
nuget.GetDataContext() : nuget.ServiceTypes.SimpleDataContextTypes.V2FeedContext


Get a simplified data context for this OData Service. By default, no credentials are set

nuget.GetDataContext(uri: System.Uri) : nuget.ServiceTypes.SimpleDataContextTypes.V2FeedContext


Get a simplified data context for this OData Service. By default, no credentials are set
val packagesId : string list

Full name: Script.packagesId
namespace System
namespace System.Linq
val packages_throws_error : unit -> nuget.ServiceTypes.V2FeedPackage list

Full name: Script.packages_throws_error
val query : Linq.QueryBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
val p : nuget.ServiceTypes.V2FeedPackage
property nuget.ServiceTypes.SimpleDataContextTypes.V2FeedContext.Packages: System.Data.Services.Client.DataServiceQuery<nuget.ServiceTypes.V2FeedPackage>


Gets the 'Packages' entities from the OData Service. This property may be used as the source in a query expression.
custom operation: where (bool)

Calls Linq.QueryBuilder.Where
(extension) System.Collections.Generic.IEnumerable.Contains<'TSource>(value: 'TSource) : bool
(extension) System.Collections.Generic.IEnumerable.Contains<'TSource>(value: 'TSource, comparer: System.Collections.Generic.IEqualityComparer<'TSource>) : bool
property nuget.ServiceTypes.V2FeedPackage.Id: string
property nuget.ServiceTypes.V2FeedPackage.IsAbsoluteLatestVersion: bool
property nuget.ServiceTypes.V2FeedPackage.IsLatestVersion: bool
custom operation: select ('Result)

Calls Linq.QueryBuilder.Select
module Seq

from Microsoft.FSharp.Collections
val toList : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.Seq.toList
namespace Microsoft.FSharp.Quotations
module Patterns

from Microsoft.FSharp.Quotations
val inList : membr:Expr<('a -> 'b)> -> values:'b list -> Expr<('a -> bool)> (requires equality)

Full name: Script.inList
val membr : Expr<('a -> 'b)> (requires equality)
Multiple items
type Expr =
  override Equals : obj:obj -> bool
  member GetFreeVars : unit -> seq<Var>
  member Substitute : substitution:(Var -> Expr option) -> Expr
  member ToString : full:bool -> string
  member CustomAttributes : Expr list
  member Type : Type
  static member AddressOf : target:Expr -> Expr
  static member AddressSet : target:Expr * value:Expr -> Expr
  static member Application : functionExpr:Expr * argument:Expr -> Expr
  static member Applications : functionExpr:Expr * arguments:Expr list list -> Expr
  ...

Full name: Microsoft.FSharp.Quotations.Expr

--------------------
type Expr<'T> =
  inherit Expr
  member Raw : Expr

Full name: Microsoft.FSharp.Quotations.Expr<_>
val values : 'b list (requires equality)
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
type bool = System.Boolean

Full name: Microsoft.FSharp.Core.bool
active recognizer Lambda: Expr -> (Var * Expr) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |Lambda|_| )
active recognizer PropertyGet: Expr -> (Expr option * System.Reflection.PropertyInfo * Expr list) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |PropertyGet|_| )
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val v : 'b (requires equality)
val a : 'a
val reduce : reduction:('T -> 'T -> 'T) -> source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.reduce
val a : Expr<('a -> bool)>
val b : Expr<('a -> bool)>
val x : 'a
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
val packages : nuget.ServiceTypes.V2FeedPackage list

Full name: Script.packages
val x : Package
Raw view Test code New version

More information

Link:http://fssnip.net/ks
Posted:10 years ago
Author:Mauricio Scheffer
Tags: quotations