Skip to content

Commit baf3dc5

Browse files
work to address feature #214 Expose an additional Table type when ResultType.DataTable is used
* add DesignTime.GetDataTableType to encapsulate creation of Table type (might make the type name a parameter in later consolidation, see note) * when ResultType.DataTable is used, add the ProvidedType (which was already of DataTable type) as a member to SqlCommandProvider provided type * add a simple unit test which shows that we can specify the type explicitly (I've removed importing ProgrammabilityTest as it is only needed for a single SqlProgrammabilityProvider definition, better to not couple test modules too much) Note: I've only changed SqlCommandProvider, but I noticed there is some code duplication already for the SqlClient provider itself in handling the DataRow and DataTable types.
1 parent 1882804 commit baf3dc5

File tree

3 files changed

+27
-11
lines changed

3 files changed

+27
-11
lines changed

src/SqlClient.Tests/DataTablesTests.fs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ open FSharp.Data
99
open FSharp.Data.SqlClient
1010
open Xunit
1111

12-
open ProgrammabilityTest
13-
12+
type AdventureWorks = SqlProgrammabilityProvider<ConnectionStrings.AdventureWorksNamed>
1413
//Tables types structured as: [TypeAlias].[Namespace].Tables.[TableName]
1514
type ShiftTable = AdventureWorks.HumanResources.Tables.Shift
1615
type ProductCostHistory = AdventureWorks.Production.Tables.ProductCostHistory
1716

1817
type GetRowCount = SqlCommandProvider<"SELECT COUNT(*) FROM HumanResources.Shift", ConnectionStrings.AdventureWorksNamed, SingleRow = true>
1918
type GetShiftTableData = SqlCommandProvider<"SELECT * FROM HumanResources.Shift", ConnectionStrings.AdventureWorksNamed, ResultType.DataReader>
20-
19+
type GetArbitraryDataAsDataTable = SqlCommandProvider<"select 1 a, 2 b, 3 c", ConnectionStrings.AdventureWorksNamed, ResultType.DataTable>
2120
type DataTablesTests() =
2221

2322
do
@@ -270,3 +269,11 @@ type DataTablesTests() =
270269
let t = new AdventureWorks.dbo.Tables.TableHavingColumnNamesWithSpaces()
271270
t.AddRow()
272271
Assert.Equal(1, t.Update())
272+
273+
[<Fact>]
274+
member __.``Can use Table type when ResultType = ResultType.DataTable`` () =
275+
let t : GetArbitraryDataAsDataTable.Table = (new GetArbitraryDataAsDataTable()).Execute()
276+
Assert.NotNull(t)
277+
Assert.Equal(1, t.Rows.[0].a)
278+
Assert.Equal(2, t.Rows.[0].b)
279+
Assert.Equal(3, t.Rows.[0].c)

src/SqlClient/DesignTime.fs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ type DesignTime private() =
150150
recordType.AddMember ctor
151151

152152
recordType
153-
153+
154154
static member internal GetDataRowType (columns: Column list) =
155155
let rowType = ProvidedTypeDefinition("Row", Some typeof<DataRow>)
156156

@@ -175,6 +175,11 @@ type DesignTime private() =
175175

176176
rowType
177177

178+
static member internal GetDataTableType dataRowType =
179+
let tableType = ProvidedTypeBuilder.MakeGenericType(typedefof<_ DataTable>, [ dataRowType ])
180+
let tableProvidedType = ProvidedTypeDefinition("Table", Some tableType)
181+
tableProvidedType
182+
178183
static member internal GetOutputTypes (outputColumns: Column list, resultType, rank: ResultRank, hasOutputParameters) =
179184
if resultType = ResultType.DataReader
180185
then
@@ -185,9 +190,9 @@ type DesignTime private() =
185190
elif resultType = ResultType.DataTable
186191
then
187192
let dataRowType = DesignTime.GetDataRowType outputColumns
188-
193+
let dataTableType = DesignTime.GetDataTableType dataRowType
189194
{
190-
ProvidedType = ProvidedTypeBuilder.MakeGenericType(typedefof<_ DataTable>, [ dataRowType ])
195+
ProvidedType = dataTableType
191196
ErasedToType = typeof<DataTable<DataRow>>
192197
ProvidedRowType = Some dataRowType
193198
ErasedToRowType = typeof<Void>
@@ -226,7 +231,6 @@ type DesignTime private() =
226231

227232
let tupleTypeName = tupleType.PartialAssemblyQualifiedName
228233
None, tupleType, <@@ Microsoft.FSharp.Reflection.FSharpValue.PreComputeTupleConstructor (Type.GetType (tupleTypeName)) @@>
229-
//None, tupleType, <@@ fun values -> Type.GetType(tupleTypeName, throwOnError = true).GetConstructors().[0].Invoke(values) @@>
230234

231235
let nullsToOptions = QuotationsFactory.MapArrayNullableItems(outputColumns, "MapArrayObjItemToOption")
232236
let combineWithNullsToOptions = typeof<QuotationsFactory>.GetMethod("GetMapperWithNullsToOptions")
@@ -241,7 +245,7 @@ type DesignTime private() =
241245
Some( typedefof<_ option>), typedefof<_ option>.MakeGenericType([| erasedToRowType |])
242246
else //ResultRank.ScalarValue
243247
None, erasedToRowType
244-
248+
245249
{
246250
ProvidedType =
247251
if providedRowType.IsSome && genericOutputType.IsSome
@@ -499,4 +503,4 @@ type DesignTime private() =
499503
if factoryMethodName.IsSome
500504
then
501505
yield upcast ProvidedMethod(factoryMethodName.Value, parameters2, returnType = cmdProvidedType, IsStaticMethod = true, InvokeCode = body2)
502-
]
506+
]

src/SqlClient/SqlCommandProvider.fs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,13 @@ type public SqlCommandProvider(config : TypeProviderConfig) as this =
141141
do
142142
cmdProvidedType.AddMember(ProvidedProperty("ConnectionStringOrName", typeof<string>, [], IsStatic = true, GetterCode = fun _ -> <@@ connectionStringOrName @@>))
143143

144-
do //Record
144+
do
145+
//for ResultType.Record and ResultType.DataTable
145146
output.ProvidedRowType |> Option.iter cmdProvidedType.AddMember
147+
148+
if resultType = ResultType.DataTable then
149+
// add .Table
150+
output.ProvidedType |> cmdProvidedType.AddMember
146151

147152
do //ctors
148153
let designTimeConfig =
@@ -218,4 +223,4 @@ type public SqlCommandProvider(config : TypeProviderConfig) as this =
218223
reader.ReadToEnd())
219224
if not (task.Wait(TimeSpan.FromSeconds(1.))) then failwithf "Couldn't read command from file %s" path
220225
task.Result, Some watcher
221-
| _ -> commandTextOrPath, None
226+
| _ -> commandTextOrPath, None

0 commit comments

Comments
 (0)