Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/fsprojects/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
johnc-j committed Jul 21, 2016
2 parents 9901760 + da7bc5b commit aeb7925
Show file tree
Hide file tree
Showing 14 changed files with 524 additions and 176 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ The goal is to create a provider which allows lightweight access to your Azure s

Support exists reading and writing from Blobs, Tables and Queues, as well as fallback to the standard .NET Azure SDK.

[![AppVeyor build status](https://ci.appveyor.com/api/projects/status/github/fsprojects/AzureStorageTypeProvider?svg=true)](https://ci.appveyor.com/project/fsprojectsgit/azurestoragetypeprovider)

### Maintainer(s)

- [@isaacabraham](https://github.com/isaacabraham)
Expand Down
2 changes: 1 addition & 1 deletion paket.dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ nuget Unquote
nuget WindowsAzure.Storage 6.0.0
nuget xunit 1.9.2
nuget xunit.runners 1.9.2
nuget xunit.runner.visualstudio version_in_path: true
nuget FSharp.Formatting
nuget Deedle
nuget FSharp.Charting
Expand All @@ -16,4 +17,3 @@ nuget Newtonsoft.Json 6.0.8

github fsprojects/FSharp.TypeProviders.StarterPack src/ProvidedTypes.fsi
github fsprojects/FSharp.TypeProviders.StarterPack src/ProvidedTypes.fs
github fsprojects/FSharp.TypeProviders.StarterPack src/DebugProvidedTypes.fs
34 changes: 16 additions & 18 deletions paket.lock
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
REDIRECTS: ON
NUGET
remote: https://nuget.org/api/v2
specs:
remote: https://www.nuget.org/api/v2
Deedle (1.2.4)
FAKE (4.4.5)
FSharp.Charting (0.90.12)
FSharp.Compiler.Service (0.0.90)
FSharp.Core (3.1.2.5)
FSharp.Formatting (2.11.0)
FSharp.Formatting (2.11)
FSharp.Compiler.Service (>= 0.0.90 <= 1.3)
FSharpVSPowerTools.Core (1.9.0)
FSharpVSPowerTools.Core (1.9.0)
FSharpVSPowerTools.Core (1.9)
FSharpVSPowerTools.Core (1.9)
FSharp.Compiler.Service (>= 0.0.90)
FsUnit.xUnit (1.3.1)
xunit (1.9.2)
Microsoft.Azure.KeyVault.Core (1.0.0) - framework: wpv8.0, >= net40
Microsoft.Data.Edm (5.6.4) - framework: winv4.5, wpv8.1, wpv8.0, >= net40
Microsoft.Data.OData (5.6.4) - framework: winv4.5, wpv8.1, wpv8.0, >= net40
Microsoft.Azure.KeyVault.Core (1.0) - framework: >= net40, wpv8.0
Microsoft.Data.Edm (5.6.4) - framework: >= net40, winv4.5, wpv8.0, wpav8.1
Microsoft.Data.OData (5.6.4) - framework: >= net40, winv4.5, wpv8.0, wpav8.1
Microsoft.Data.Edm (5.6.4)
System.Spatial (5.6.4)
Microsoft.Data.Services.Client (5.6.4) - framework: >= net40
Microsoft.Data.OData (5.6.4)
Newtonsoft.Json (6.0.8)
NuGet.CommandLine (2.8.6)
System.Spatial (5.6.4) - framework: winv4.5, wpv8.1, wpv8.0, >= net40
Unquote (3.0.0)
WindowsAzure.Storage (6.0.0)
Microsoft.Azure.KeyVault.Core (>= 1.0.0) - framework: wpv8.0, >= net40
Microsoft.Data.OData (>= 5.6.4) - framework: winv4.5, wpv8.1, wpv8.0, >= net40
System.Spatial (5.6.4) - framework: >= net40, winv4.5, wpv8.0, wpav8.1
Unquote (3.0)
WindowsAzure.Storage (6.0)
Microsoft.Azure.KeyVault.Core (>= 1.0) - framework: >= net40, wpv8.0
Microsoft.Data.OData (>= 5.6.4) - framework: >= net40, winv4.5, wpv8.0, wpav8.1
Microsoft.Data.Services.Client (>= 5.6.4) - framework: >= net40
Newtonsoft.Json (>= 6.0.8) - framework: winv4.5, wpv8.1, wpv8.0, >= net40
Newtonsoft.Json (>= 6.0.8) - framework: >= net40, winv4.5, wpv8.0, wpav8.1
xunit (1.9.2)
xunit.runner.visualstudio (2.1.0) - version_in_path: true
xunit.runners (1.9.2)
GITHUB
remote: fsprojects/FSharp.TypeProviders.StarterPack
specs:
src/DebugProvidedTypes.fs (f1234ba078dad7cbb674b1d1ab8b94f92f827911)
src/ProvidedTypes.fs (f1234ba078dad7cbb674b1d1ab8b94f92f827911)
src/ProvidedTypes.fsi (f1234ba078dad7cbb674b1d1ab8b94f92f827911)
src/ProvidedTypes.fs (dfbca9b83fb70067e85abddcb8b89332aae4c28d)
src/ProvidedTypes.fsi (dfbca9b83fb70067e85abddcb8b89332aae4c28d)

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion src/FSharp.Azure.StorageTypeProvider/Shared.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ let internal ofNullable (value : Nullable<_>) =

let internal toNullable = function
| Some x -> Nullable x
| None -> Nullable()
| None -> Nullable()

let internal ofObj (value) = if value = null then None else Some value

let internal toObj = function
| Some x -> x
| None -> null
78 changes: 60 additions & 18 deletions src/FSharp.Azure.StorageTypeProvider/Table/ProvidedTableTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,36 @@ type AzureTable internal (defaultConnection, tableName) =
let getConnectionDetails (insertMode, connectionString) =
defaultArg insertMode TableInsertMode.Insert, defaultArg connectionString defaultConnection
let getTableForConnection = getTable tableName

/// Gets a handle to the Azure SDK client for this table.
member __.AsCloudTable(?connectionString) = getTableForConnection (defaultArg connectionString defaultConnection)

/// Inserts a batch of entities into the table, using all public properties on the object as fields.
member __.Insert(entities : seq<Partition * Row * 'b>, ?insertMode, ?connectionString) =
let buildInsertParams insertMode connectionString (entities : seq<Partition * Row * 'b>) =
let insertMode, connectionString = getConnectionDetails (insertMode, connectionString)
let table = getTableForConnection connectionString
let insertOp = createInsertOperation insertMode

let propBuilders =
typeof<'b>.GetProperties(Reflection.BindingFlags.Public ||| Reflection.BindingFlags.Instance)
|> Seq.map (fun prop entity -> prop.Name, prop.GetValue(entity, null))
|> Seq.toArray
entities
|> Seq.map (fun (partitionKey, rowKey, entity) ->
LightweightTableEntity(partitionKey, rowKey, DateTimeOffset.MinValue,
propBuilders
|> Seq.map (fun builder -> builder (entity))
|> Map.ofSeq))
|> Seq.map buildDynamicTableEntity
|> executeBatchOperation insertOp table

let tblEntities =
entities
|> Seq.map (fun (partitionKey, rowKey, entity) ->
let values = propBuilders |> Seq.map (fun builder -> builder entity) |> Map.ofSeq
LightweightTableEntity(partitionKey, rowKey, DateTimeOffset.MinValue, values) |> buildDynamicTableEntity)
tblEntities, insertOp, table

/// Gets a handle to the Azure SDK client for this table.
member __.AsCloudTable(?connectionString) = getTableForConnection (defaultArg connectionString defaultConnection)

/// Inserts a batch of entities into the table, using all public properties on the object as fields.
member __.Insert(entities : seq<Partition * Row * 'b>, ?insertMode, ?connectionString) =
let tblEntities, insertOp, table = buildInsertParams insertMode connectionString entities
tblEntities |> executeBatchOperation insertOp table

/// Inserts a batch of entities into the table, using all public properties on the object as fields.
member __.InsertAsync(entities : seq<Partition * Row * 'b>, ?insertMode, ?connectionString) = async{
let tblEntities, insertOp, table = buildInsertParams insertMode connectionString entities
return! tblEntities |> executeBatchOperationAsync insertOp table }

/// Inserts a single entity into the table, using public properties on the object as fields.
member this.Insert(partitionKey, rowKey, entity, ?insertMode, ?connectionString) =
Expand All @@ -41,26 +49,60 @@ type AzureTable internal (defaultConnection, tableName) =
|> Seq.head
|> snd
|> Seq.head

/// Inserts a single entity into the table asynchronously, using public properties on the object as fields.
member this.InsertAsync(partitionKey, rowKey, entity, ?insertMode, ?connectionString) = async{
let insertMode, connectionString = getConnectionDetails (insertMode, connectionString)
let! insertRes = this.InsertAsync([ partitionKey, rowKey, entity ], insertMode, connectionString)
return
insertRes
|> Seq.head
|> snd
|> Seq.head }

/// Deletes a batch of entities from the table using the supplied pairs of Partition and Row keys.
/// Deletes a batch of entities from the table using the supplied pairs of Partition and Row keys.
member __.Delete(entities, ?connectionString) =
let table = getTableForConnection (defaultArg connectionString defaultConnection)
entities
|> Seq.map (fun entityId ->
let Partition(partitionKey), Row(rowKey) = entityId
DynamicTableEntity(partitionKey, rowKey, ETag = "*"))
let Partition(partitionKey), Row(rowKey) = entityId
DynamicTableEntity(partitionKey, rowKey, ETag = "*"))
|> executeBatchOperation TableOperation.Delete table

/// Asynchronously deletes a batch of entities from the table using the supplied pairs of Partition and Row keys.
member __.DeleteAsync(entities, ?connectionString) = async {
let table = getTableForConnection (defaultArg connectionString defaultConnection)
return! entities
|> Seq.map (fun entityId ->
let Partition(partitionKey), Row(rowKey) = entityId
DynamicTableEntity(partitionKey, rowKey, ETag = "*"))
|> executeBatchOperationAsync TableOperation.Delete table }

/// Deletes an entire partition from the table
member __.DeletePartition(partitionKey, ?connectionString) =
let table = getTableForConnection (defaultArg connectionString defaultConnection)
let filter = Table.TableQuery.GenerateFilterCondition ("PartitionKey", Table.QueryComparisons.Equal, partitionKey)
let projection = [|"RowKey"|]

(new Table.TableQuery<Table.DynamicTableEntity>()).Where(filter).Select(projection)
|> table.ExecuteQuery
|> Seq.map(fun e -> (Partition(e.PartitionKey), Row(e.RowKey)))
|> __.Delete
|> ignore
|> ignore

/// Asynchronously deletes an entire partition from the table
member __.DeletePartitionAsync(partitionKey, ?connectionString) = async {
let table = getTableForConnection (defaultArg connectionString defaultConnection)
let connStringToUse =
match connectionString with
| Some c -> c
| None -> defaultConnection
let filter = Table.TableQuery.GenerateFilterCondition ("PartitionKey", Table.QueryComparisons.Equal, partitionKey)
let! response = executeGenericQueryAsync connStringToUse table.Name Int32.MaxValue filter (fun e -> (Partition(e.PartitionKey), Row(e.RowKey)))
return!
response
|> __.DeleteAsync
|> Async.Ignore }

/// Gets the name of the table.
member __.Name = tableName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,17 @@ let buildTableEntityMembers (parentTableType:ProvidedTypeDefinition, parentTable
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ], parentTableEntityType.MakeArrayType(),
InvokeCode = (fun args -> <@@ getPartitionRows %%args.[1] %%args.[2] tableName @@>))
getPartition.AddXmlDocDelayed <| fun _ -> "Eagerly retrieves all entities in a table partition by its key."

let getPartitionAsync =
ProvidedMethod
("GetPartitionAsync",
[ ProvidedParameter("key", typeof<string>)
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ],
typeof<Async<_>>.GetGenericTypeDefinition().MakeGenericType(parentTableEntityType.MakeArrayType()),
InvokeCode = (fun args -> <@@ getPartitionRowsAsync %%args.[1] %%args.[2] tableName @@>))
getPartitionAsync.AddXmlDocDelayed <| fun _ -> "Asynchronously retrieves all entities in a table partition by its key."

let queryBuilderType, childTypes = TableQueryBuilder.createTableQueryType parentTableEntityType connection tableName propertiesCreated

let executeQuery =
ProvidedMethod
("Query",
Expand All @@ -116,20 +125,46 @@ let buildTableEntityMembers (parentTableType:ProvidedTypeDefinition, parentTable
(typeof<Option<_>>).GetGenericTypeDefinition().MakeGenericType(parentTableEntityType),
InvokeCode = (fun args -> <@@ getEntity (%%args.[1] : Row) (%%args.[2] : Partition) (%%args.[3] : string) tableName @@>))
getEntity.AddXmlDocDelayed <| fun _ -> "Gets a single entity based on the row and partition key."
let getEntityAsync =
let returnType =
let optionType = typeof<Option<_>>.GetGenericTypeDefinition().MakeGenericType(parentTableEntityType)
typeof<Async<_>>.GetGenericTypeDefinition().MakeGenericType(optionType)
ProvidedMethod
("GetAsync",
[ ProvidedParameter("rowKey", typeof<Row>)
ProvidedParameter("partitionKey", typeof<Partition>)
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ],
returnType,
InvokeCode = (fun args -> <@@ getEntityAsync (%%args.[1] : Row) (%%args.[2] : Partition) (%%args.[3] : string) tableName @@>))
getEntityAsync.AddXmlDocDelayed <| fun _ -> "Gets a single entity based on the row and partition key asynchronously."
let deleteEntity =
ProvidedMethod
("Delete",
[ ProvidedParameter("entity", parentTableEntityType)
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ], returnType = typeof<TableResponse>,
InvokeCode = (fun args -> <@@ deleteEntity %%args.[2] tableName %%args.[1] @@>))
deleteEntity.AddXmlDocDelayed <| fun _ -> "Deletes a single entity from the table."
let deleteEntityAsync =
ProvidedMethod
("DeleteAsync",
[ ProvidedParameter("entity", parentTableEntityType)
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ], returnType = typeof<Async<TableResponse>>,
InvokeCode = (fun args -> <@@ deleteEntityAsync %%args.[2] tableName %%args.[1] @@>))
deleteEntityAsync.AddXmlDocDelayed <| fun _ -> "Deletes a single entity from the table asynchronously."
let deleteEntities =
ProvidedMethod
("Delete",
[ ProvidedParameter("entities", parentTableEntityType.MakeArrayType())
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ], returnType = typeof<(string * TableResponse []) []>,
InvokeCode = (fun args -> <@@ deleteEntities %%args.[2] tableName %%args.[1] @@>))
deleteEntities.AddXmlDocDelayed <| fun _ -> "Deletes a batch of entities from the table."
let deleteEntitiesAsync =
ProvidedMethod
("DeleteAsync",
[ ProvidedParameter("entities", parentTableEntityType.MakeArrayType())
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ], returnType = typeof<Async<(string * TableResponse []) []>>,
InvokeCode = (fun args -> <@@ deleteEntitiesAsync %%args.[2] tableName %%args.[1] @@>))
deleteEntitiesAsync.AddXmlDocDelayed <| fun _ -> "Deletes a batch of entities from the table asynchronously."
let insertEntity =
ProvidedMethod
("Insert",
Expand All @@ -138,6 +173,14 @@ let buildTableEntityMembers (parentTableType:ProvidedTypeDefinition, parentTable
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ], returnType = typeof<TableResponse>,
InvokeCode = (fun args -> <@@ insertEntity (%%args.[3] : string) tableName %%args.[2] (%%args.[1] : LightweightTableEntity) @@>))
insertEntity.AddXmlDocDelayed <| fun _ -> "Inserts a single entity with the inferred table schema into the table."
let insertEntityAsync =
ProvidedMethod
("InsertAsync",
[ ProvidedParameter("entity", parentTableEntityType)
ProvidedParameter("insertMode", typeof<TableInsertMode>, optionalValue = TableInsertMode.Insert)
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ], returnType = typeof<Async<TableResponse>>,
InvokeCode = (fun args -> <@@ insertEntityAsync (%%args.[3] : string) tableName %%args.[2] (%%args.[1] : LightweightTableEntity) @@>))
insertEntityAsync.AddXmlDocDelayed <| fun _ -> "Asynchronously inserts a single entity with the inferred table schema into the table."
let insertEntities =
ProvidedMethod
("Insert",
Expand All @@ -146,5 +189,22 @@ let buildTableEntityMembers (parentTableType:ProvidedTypeDefinition, parentTable
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ], returnType = typeof<(string * TableResponse [])[]>,
InvokeCode = (fun args -> <@@ insertEntityBatch (%%args.[3] : string) tableName %%args.[2] (%%args.[1] : LightweightTableEntity []) @@>))
insertEntities.AddXmlDocDelayed <| fun _ -> "Inserts a batch of entities with the inferred table schema into the table."
let insertEntitiesAsync =
ProvidedMethod
("InsertAsync",
[ ProvidedParameter("entities", parentTableEntityType.MakeArrayType())
ProvidedParameter("insertMode", typeof<TableInsertMode>, optionalValue = TableInsertMode.Insert)
ProvidedParameter("connectionString", typeof<string>, optionalValue = connection) ], returnType = typeof<Async<(string * TableResponse [])[]>>,
InvokeCode = (fun args -> <@@ insertEntityBatchAsync (%%args.[3] : string) tableName %%args.[2] (%%args.[1] : LightweightTableEntity []) @@>))
insertEntitiesAsync.AddXmlDocDelayed <| fun _ -> "Asynchronously inserts a batch of entities with the inferred table schema into the table."

domainType.AddMembers(queryBuilderType :: childTypes)
[ getPartition; getEntity; buildQuery; executeQuery; deleteEntity; deleteEntities; insertEntity; insertEntities ])

[ getPartition; getPartitionAsync
getEntity; getEntityAsync
buildQuery
executeQuery
deleteEntity; deleteEntityAsync
deleteEntities; deleteEntitiesAsync
insertEntity; insertEntityAsync
insertEntities; insertEntitiesAsync ])
Loading

0 comments on commit aeb7925

Please sign in to comment.