Search code examples
mysqlf#app-configtype-providers

Get and use connection string from App.config F# AppSettings provider


I've scoured the net for hours and can't do it, so I'm hoping someone can help me with this one.

I've tried to use App.Config directly but constantly had null return. So I've turned to an AppSetting typerprovider. This does return the string expected but I have a problem that no-one so far (via google) has an answer for.

open System.Linq
open FSharp.Data.Sql
open MySql.Data
open FSharp.Configuration 
type Settings = AppSettings<"App.config">

let c = Settings.ConnectionStrings.RaspberryPi 

[<Literal>]
let connection = c //quick attempt to turn c into a literal.

type sql = SqlDataProvider< ConnectionString = c,  ResolutionPath = @"C:\Program Files (x86)\MySQL\MySQL Connector Net 6.9.7\Assemblies\v4.5\"  >

I get the message that "This is not a valid constant expression or custom attribute value."

Whilst I'm able to print out the setting the Appsettings provider obtains, it seems I can't use it to connect to a database.

This is the App.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
    </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <connectionStrings>
    <add name="raspberryPi" providerName="FSharp.Data.SqlProvider" connectionString="Server=SomeDB.rds.amazonaws.com:3306;Database=SomeDB;Uid=SomeUser;Pwd=APassword" />
  </connectionStrings>
</configuration>

I've turned to the typeprovider as my earlier approach to using System.Configuration to read the file refused to work right, even when I blitzed the output folders and made sure that all the config files were updated.

Please note I'm using a MySQL type provider as well!

Whilst I could use the string directly in the code, my understanding is this is a terrible idea for production code.

Any help would be very gratefully received - I don't mind admitting that this has burned hours today, to my great surprise.

Note - may help others: I've also looked at this answer, this article and this one from the MS Forums


Solution

  • That won't work, unfortunately. The connection string is being exposed by a read/write static property (Settings.ConnectionStrings.RaspberryPi), which can't be treated as a constant/literal (by design).

    It would be possible for someone to write a type provider that does what you want by exposing the connection strings as literal static fields instead of read/write properties, but that's not compatible with updating the application settings, which seems to be a goal of the existing provider. Perhaps you could consider submitting a feature request to the AppSettings project to enable a separate mode that would behave how you want.