Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/SqlClient/ISqlCommand.fs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ open System
open System.Data
open System.Data.SqlClient
open System.Reflection
open System.Text.RegularExpressions
open FSharp.Data.SqlClient
open FSharp.Data.SqlClient.Internals
open System.Linq
Expand All @@ -33,6 +34,23 @@ module Seq =
| [| x |] -> Some x
| _ -> invalidArg "source" "The input sequence contains more than one element."

module internal TypeResolution =

// Resolves a type by its assembly-qualified name, with a version-tolerant fallback.
// The design-time DLL runs inside the F# compiler process and bakes the compiler's FSharp.Core
// version into item type names. If the user's project references a different FSharp.Core version,
// Type.GetType with the exact name fails with FileLoadException. Stripping version/culture/token
// from the assembly reference lets the runtime's binding logic find the correct assembly.
// See: https://github.com/fsprojects/FSharp.Data.SqlClient/issues/433
let resolveType (typeName: string) =
match Type.GetType(typeName, throwOnError = false) with
| null ->
let stripped = Regex.Replace(typeName, @",\s*Version=[^,\[\]]+", "")
let stripped = Regex.Replace(stripped, @",\s*Culture=[^,\[\]]+", "")
let stripped = Regex.Replace(stripped, @",\s*PublicKeyToken=[^,\[\]]+", "")
Type.GetType(stripped, throwOnError = true)
| t -> t

[<CompilerMessageAttribute("This API supports the FSharp.Data.SqlClient infrastructure and is not intended to be used directly from your code.", 101, IsHidden = true)>]
type RowMapping = obj[] -> obj

Expand Down Expand Up @@ -108,7 +126,7 @@ type ``ISqlCommand Implementation``(cfg: DesignTimeConfig, connection: Connectio
notImplemented
| rowMapping, itemTypeName ->
assert ((not(isNull rowMapping)) && (not (isNull itemTypeName)))
let itemType = Type.GetType( itemTypeName, throwOnError = true)
let itemType = TypeResolution.resolveType itemTypeName

let executeHandle =
typeof<``ISqlCommand Implementation``>
Expand Down
Loading