From 419a2b2382c96a2407f77487a47fd18cb8a0ae21 Mon Sep 17 00:00:00 2001 From: Erlis Vidal Date: Mon, 30 Jul 2018 13:37:08 -0400 Subject: [PATCH] ADDED: First version for what could be used to avoid the Temp Table errors in stored procedure --- src/SqlClient/SqlClientProvider.fs | 39 +++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/SqlClient/SqlClientProvider.fs b/src/SqlClient/SqlClientProvider.fs index 7af60581..e1285f48 100644 --- a/src/SqlClient/SqlClientProvider.fs +++ b/src/SqlClient/SqlClientProvider.fs @@ -29,6 +29,19 @@ type SqlProgrammabilityProvider(config : TypeProviderConfig) as this = let cache = new MemoryCache(name = this.GetType().Name) let methodsCache = new MemoryCache(name = this.GetType().Name) + + let splitKeyVal (s : string) = + match s.Split(':') with + | [|key; value|] -> (key.Trim().ToLower(), value) + |_ -> invalidArg "s" "parameter must be of type key:value" + + let mapFromString (s : string) = + match s with + | "" -> Map.empty + | x -> + x.Split('|') + |> Array.map splitKeyVal + |> Map.ofArray do this.Disposing.Add <| fun _ -> @@ -44,10 +57,11 @@ type SqlProgrammabilityProvider(config : TypeProviderConfig) as this = ProvidedStaticParameter("ConfigFile", typeof, "") ProvidedStaticParameter("DataDirectory", typeof, "") ProvidedStaticParameter("UseReturnValue", typeof, false) - ProvidedStaticParameter("ResultType", typeof, ResultType.Records) + ProvidedStaticParameter("ResultType", typeof, ResultType.Records) + ProvidedStaticParameter("ProcResultSets", typeof, "") ], instantiationFunction = (fun typeName args -> - let root = lazy this.CreateRootType(typeName, unbox args.[0], unbox args.[1], unbox args.[2], unbox args.[3], unbox args.[4]) + let root = lazy this.CreateRootType(typeName, unbox args.[0], unbox args.[1], unbox args.[2], unbox args.[3], unbox args.[4], unbox args.[5] |> mapFromString) cache.GetOrAdd(typeName, root) ) ) @@ -59,6 +73,7 @@ type SqlProgrammabilityProvider(config : TypeProviderConfig) as this = The name of the data directory that replaces |DataDirectory| in connection strings. The default value is the project or script directory. To be documented. A value that defines structure of result: Records, Tuples, DataTable, or SqlDataReader, this affects only Stored Procedures. +String defining a dictionary using the format key1:value1|key2:value2|... """ this.AddNamespace(nameSpace, [ providerType ]) @@ -70,7 +85,7 @@ type SqlProgrammabilityProvider(config : TypeProviderConfig) as this = |> defaultArg <| base.ResolveAssembly args - member internal this.CreateRootType( typeName, connectionStringOrName, configFile, dataDirectory, useReturnValue, resultType) = + member internal this.CreateRootType(typeName, connectionStringOrName, configFile, dataDirectory, useReturnValue, resultType, procResultSets) = if String.IsNullOrWhiteSpace connectionStringOrName then invalidArg "ConnectionStringOrName" "Value is empty!" let designTimeConnectionString = DesignTimeConnectionString.Parse(connectionStringOrName, config.ResolutionFolder, configFile) @@ -124,7 +139,7 @@ type SqlProgrammabilityProvider(config : TypeProviderConfig) as this = schemaType.AddMembersDelayed <| fun() -> [ - let routines = this.Routines(conn, schemaType.Name, udttsPerSchema, resultType, designTimeConnectionString, useReturnValue, uomPerSchema) + let routines = this.Routines(conn, schemaType.Name, udttsPerSchema, resultType, designTimeConnectionString, useReturnValue, uomPerSchema, procResultSets) routines |> List.iter tagProvidedType yield! routines @@ -159,11 +174,16 @@ type SqlProgrammabilityProvider(config : TypeProviderConfig) as this = yield units ] - member internal __.Routines(conn, schema, uddtsPerSchema, resultType, designTimeConnectionString, useReturnValue, unitsOfMeasurePerSchema) = + member internal __.Routines(conn, schema, uddtsPerSchema, resultType, designTimeConnectionString, useReturnValue, unitsOfMeasurePerSchema, procResultSets: Map) = [ use _ = conn.UseLocally() let isSqlAzure = conn.IsSqlAzure let routines = conn.GetRoutines( schema, isSqlAzure) + + let appendResultSet (commandText: string) = + commandText + " " + defaultArg (procResultSets.TryFind (commandText.ToLower()) ) "" + + for routine in routines do let cmdProvidedType = ProvidedTypeDefinition(snd routine.TwoPartName, Some typeof<``ISqlCommand Implementation``>, HideObjectMethods = true) @@ -176,8 +196,15 @@ type SqlProgrammabilityProvider(config : TypeProviderConfig) as this = use __ = conn.UseLocally() let parameters = conn.GetParameters( routine, isSqlAzure, useReturnValue) + // there is a typo in function name `ToCommantText` should be Command instead of Commant let commandText = routine.ToCommantText(parameters) - let outputColumns = DesignTime.GetOutputColumns(conn, commandText, parameters, routine.IsStoredProc) + + let commandTextWithResultSets = + if not routine.IsStoredProc + then commandText + else commandText |> appendResultSet + + let outputColumns = DesignTime.GetOutputColumns(conn, commandTextWithResultSets, parameters, routine.IsStoredProc) let rank = if routine.Type = ScalarValuedFunction then ResultRank.ScalarValue else ResultRank.Sequence let hasOutputParameters = parameters |> List.exists (fun x -> x.Direction.HasFlag( ParameterDirection.Output))