Skip to content

Commit 82256c5

Browse files
Merge pull request #217 from smoothdeveloper/expose-table-type
Expose an additional Table type when ResultType.DataTable is used
2 parents c9116ae + 649df36 commit 82256c5

File tree

5 files changed

+46
-9
lines changed

5 files changed

+46
-9
lines changed

docs/content/output.fsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ let table = (new QueryPersonInfoSingletoneDataTable()).AsyncExecute(PersonId = 2
113113
for row in table.Rows do
114114
printfn "Person info:Id - %i,FirstName - %O,LastName - %O" row.PersonID row.FirstName row.LastName
115115

116+
// you can refer to the table type
117+
let table2 : QueryPersonInfoSingletoneDataTable.Table = (new QueryPersonInfoSingletoneDataTable()).Execute(PersonId = 2)
118+
119+
// you can refer to the row type
120+
for row : QueryPersonInfoSingletoneDataTable.Table.Row in table2.Rows do
121+
printfn "Person info:Id - %i,FirstName - %O,LastName - %O" row.PersonID row.FirstName row.LastName
122+
123+
116124
(**
117125
118126
* Same as previous but using `SqlProgrammabilityProvider<...>`

src/SqlClient.Tests/DataTablesTests.fs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ type ProductCostHistory = AdventureWorks.Production.Tables.ProductCostHistory
1717

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

2323
do
@@ -270,3 +270,14 @@ type DataTablesTests() =
270270
let t = new AdventureWorks.dbo.Tables.TableHavingColumnNamesWithSpaces()
271271
t.AddRow()
272272
Assert.Equal(1, t.Update())
273+
274+
[<Fact>]
275+
member __.``Can use Table type when ResultType = ResultType.DataTable`` () =
276+
let t : GetArbitraryDataAsDataTable.Table = (new GetArbitraryDataAsDataTable()).Execute()
277+
for (r: GetArbitraryDataAsDataTable.Table.Row) in t.Rows do
278+
()
279+
280+
Assert.NotNull(t)
281+
Assert.Equal(1, t.Rows.[0].a)
282+
Assert.Equal(2, t.Rows.[0].b)
283+
Assert.Equal(3, t.Rows.[0].c)

src/SqlClient/DesignTime.fs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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,13 @@ type DesignTime private() =
185190
elif resultType = ResultType.DataTable
186191
then
187192
let dataRowType = DesignTime.GetDataRowType outputColumns
193+
let dataTableType = DesignTime.GetDataTableType dataRowType
194+
195+
// add .Row to .Table
196+
dataTableType.AddMember dataRowType
188197

189198
{
190-
ProvidedType = ProvidedTypeBuilder.MakeGenericType(typedefof<_ DataTable>, [ dataRowType ])
199+
ProvidedType = dataTableType
191200
ErasedToType = typeof<DataTable<DataRow>>
192201
ProvidedRowType = Some dataRowType
193202
ErasedToRowType = typeof<Void>
@@ -226,7 +235,6 @@ type DesignTime private() =
226235

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

231239
let nullsToOptions = QuotationsFactory.MapArrayNullableItems(outputColumns, "MapArrayObjItemToOption")
232240
let combineWithNullsToOptions = typeof<QuotationsFactory>.GetMethod("GetMapperWithNullsToOptions")
@@ -241,7 +249,7 @@ type DesignTime private() =
241249
Some( typedefof<_ option>), typedefof<_ option>.MakeGenericType([| erasedToRowType |])
242250
else //ResultRank.ScalarValue
243251
None, erasedToRowType
244-
252+
245253
{
246254
ProvidedType =
247255
if providedRowType.IsSome && genericOutputType.IsSome
@@ -499,4 +507,4 @@ type DesignTime private() =
499507
if factoryMethodName.IsSome
500508
then
501509
yield upcast ProvidedMethod(factoryMethodName.Value, parameters2, returnType = cmdProvidedType, IsStaticMethod = true, InvokeCode = body2)
502-
]
510+
]

src/SqlClient/SqlClientProvider.fs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,12 @@ type public SqlProgrammabilityProvider(config : TypeProviderConfig) as this =
540540
addRedirectToISqlCommandMethod typeof<string> "ToTraceString"
541541

542542
commands.AddMember cmdProvidedType
543-
output.ProvidedRowType |> Option.iter cmdProvidedType.AddMember
543+
if resultType = ResultType.DataTable then
544+
// if we don't do this, we get a compile error
545+
// Error The type provider 'FSharp.Data.SqlProgrammabilityProvider' reported an error: type 'Table' was not added as a member to a declaring type <type instanciation name>
546+
output.ProvidedType |> cmdProvidedType.AddMember
547+
else
548+
output.ProvidedRowType |> Option.iter cmdProvidedType.AddMember
544549

545550
let designTimeConfig =
546551
let expectedDataReaderColumns =

src/SqlClient/SqlCommandProvider.fs

Lines changed: 8 additions & 3 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
145-
output.ProvidedRowType |> Option.iter cmdProvidedType.AddMember
144+
do
145+
if resultType = ResultType.Records then
146+
// Add .Record
147+
output.ProvidedRowType |> Option.iter cmdProvidedType.AddMember
148+
elif 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)