If you take a look at the XML, it is easy to see that the WsdlService
type provider can gather the necessary information to infer types:
<service xmlns:atom="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app" xml:base="http://live.ineta.org/InetaLiveService.svc/"> <workspace> <atom:title>Default</atom:title> <collection href="LivePresentations"> <atom:title>LivePresentations</atom:title> </collection> <collection href="LiveVideos"> <atom:title>LiveVideos</atom:title> </collection> <collection href="LiveAuthors"> <atom:title>LiveAuthors</atom:title> </collection> <collection href="LiveGroups"> <atom:title>LiveGroups</atom:title> </collection> <collection href="LiveTags"> <atom:title>LiveTags</atom:title> </collection> </workspace> </service>
It is easy to write queries and check the results in a browser. For example, to retrieve the first live presentation that includes "Blend" in its abstract, I just need to enter the following URL (see Figure 7):

As you can see in the following lines, the result includes useful type information for the type provider:
<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?> <feed xml:base="http://live.ineta.org/InetaLiveService.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom"> <title type="text">LivePresentations</title> <id>http://live.ineta.org/InetaLiveService.svc/LivePresentations</id> <updated>2012-11-29T17:25:42Z</updated> <link rel="self" title="LivePresentations" href="LivePresentations" /> <entry> <id>http://live.ineta.org/InetaLiveService.svc/LivePresentations(1)</id> <title type="text"></title> <updated>2012-11-29T17:25:42Z</updated> <author> <name /> </author> <link rel="edit" title="LivePresentation" href="LivePresentations(1)" /> <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/LiveVideos" type="application/atom+xml;type=feed" title="LiveVideos" href="LivePresentations(1)/LiveVideos" /> <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/LiveTags" type="application/atom+xml;type=feed" title="LiveTags" href="LivePresentations(1)/LiveTags" /> <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/LiveAuthors" type="application/atom+xml;type=feed" title="LiveAuthors" href="LivePresentations(1)/LiveAuthors" /> <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/LiveGroup" type="application/atom+xml;type=entry" title="LiveGroup" href="LivePresentations(1)/LiveGroup" /> <category term="INETALivePublicModel.LivePresentation" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> <content type="application/xml"> <m:properties> <d:PresentationID m:type="Edm.Int32">1</d:PresentationID> <d:Title>Expression Blend 4</d:Title> <d:DeliveredOn m:type="Edm.DateTime">2010-05-08T00:00:00</d:DeliveredOn> <d:Abstract>Blend 4 - Let's get started with Blend Come join us to learn the Blend UI and see how far Blend can take your XAML projects. We will cover the controls and settings within Blend to give you a basic foundation to move forward from. Although many things will be touched upon in order to show off the gui controls, this talk is not a deep dive into XAML, building complex controls, or live data integration. It is a good foundation for those discussions to follow.</d:Abstract> <d:GroupID m:type="Edm.Int32">1</d:GroupID> </m:properties> </content> </entry> </feed>
Instead of entering OData queries in the browser, you can take advantage of the ODataService
type provider to discover the data structure as you retrieve it. The following lines show the result of a quick FSI session that uses the ODataService
type provider to connect to the INETA OData service and retrieves the first LivePresentation
.
Microsoft (R) F# Interactive version 11.0.50727.1
Copyright (c) Microsoft Corporation. All Rights Reserved.
For help type #help;;
> #r "System.Data"
#r "System.Data.Linq"
#r "FSharp.Data.TypeProviders"
open Microsoft.FSharp.Data.TypeProviders
;;
--> Referenced 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll'
--> Referenced 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.Linq.dll'
--> Referenced 'C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp\3.0\Runtime\v4.0\Type Providers\FSharp.Data.TypeProviders.dll'
> [<Literal>]
let InetaServiceAddress = "http://live.ineta.org/InetaLiveService.svc/"
type InetaCatalog = ODataService<InetaServiceAddress>
let inetaDatabase = InetaCatalog.GetDataContext()
;;
val InetaServiceAddress : string =
"http://live.ineta.org/InetaLiveService.svc/"
type InetaCatalog =
class
static member GetDataContext : unit -> InetaCatalog.ServiceTypes.SimpleDataContextTypes.INETALivePublic
+ 1 overload
nested type ServiceTypes
end
val inetaDatabase :
InetaCatalog.ServiceTypes.SimpleDataContextTypes.INETALivePublic
> let onePresentation = Seq.head inetaDatabase.LivePresentations
;;
val onePresentation : InetaCatalog.ServiceTypes.LivePresentation
> onePresentation
;;
val it : InetaCatalog.ServiceTypes.LivePresentation =
LivePresentation
{Abstract = "Blend 4 - Let's get started with Blend Come join us to learn the Blend UI and see how far Blend can take your XAML projects. We will cover the controls and settings within Blend to give you a basic foundation to move forward from. Although many things will be touched upon in order to show off the gui controls, this talk is not a deep dive into XAML, building complex controls, or live data integration. It is a good foundation for those discussions to follow.";
DeliveredOn = 5/8/2010 12:00:00 AM;
GroupID = 1;
LiveAuthors = seq [];
LiveGroup = null;
LiveTags = seq [];
LiveVideos = seq [];
PresentationID = 1;
Title = "Expression Blend 4";}
>
I just retrieved one presentation with the following line:
let onePresentation = Seq.head inetaDatabase.LivePresentations
This way, I can check the properties provided by that LivePresentation
instance. The following lines show another example of using the ODataService
type provider to retrieve the first live presentation that includes "Blend" in its abstract.
module OdataConnectivity = open System open System.Data open Microsoft.FSharp.Data.TypeProviders [<Literal>] let InetaServiceAddress = "http://live.ineta.org/InetaLiveService.svc/" type InetaCatalog = ODataService<InetaServiceAddress> let inetaDatabase = InetaCatalog.GetDataContext() let GetFirstPresentationTitleByAbstractWord abstractWord = query { for presentation in inetaDatabase.LivePresentations do where (presentation.Abstract.Contains(abstractWord)) headOrDefault } |> (fun presentation -> if presentation = null then "No matches found" else presentation.Title) let firstBlendPresentationTitle = GetFirstPresentationTitleByAbstractWord "Blend" Console.WriteLine(firstBlendPresentationTitle) let ReadAnyKey() = Console.WriteLine("Press any key to continue") Console.ReadKey() |> ignore ReadAnyKey()
This is straightforward code. InetaCatalog
is the type abbreviation (or alias) for the ODataService
type provider. The GetDataContext
static method gets a simplified data context for the OData
service. inetaDatabase
is of type InetaCatalog.ServiceTypes.SimpleDataContextTypes.INETALivePublic
. Because the type provider already established the connection and generated the necessary types, when you enter "inetaDatabase,"
IntelliSense displays the available methods, such as GetDataContext
and the ServiceTypes
with all the types required for the service as nested types.
If you enter the following lines:
let GetFirstPresentationTitleByAbstractWord abstractWord = query { for presentation in inetaDatabase.
You will notice how IntelliSense displays all the initial collections exposed by the OData
service (see Figure 8):
LiveAuthors
LiveGroups
LivePresentations
LiveTags
LiveVideos

In the previous example, the code uses LivePresentations
as the data source for a query expression. Once you start writing the lines that define the query expression, the type inference mechanism knows that presentation is of type InetaCatalog.ServiceTypes.LivePresentation
. Thus, after you write "presentation,"
IntelliSense displays the different fields available for the entity.
If you execute the code, you will see the title for an old presentation related to Blend on the console:
Expression Blend 4 Press any key to continue