I have a solution with 2 projects:
I will need to call SQL Server stored procedures, and am using FSharp.Data.TypeProviders to do the job.
type dbSchema = SqlDataConnection< "...", StoredProcedures=true >
let getDbContext connString =
match connString with
| "" -> dbSchema.GetDataContext()
| _ -> dbSchema.GetDataContext(connString)
Insert:
let insertItem dbContext item =
dbContext.CreateStoredProc(item.Stuff)
Or
let insertItem connString item =
use dbContext = getDbContext connString
dbContext.CreateStoredProc(item.Stuff)
dbContext
every time I do an insert?I don't want to expose the whole dbContext
, just certain stored procedures through the F# DAL.
Note: I need to pass in the connection string from web.config
Similar question here doesn't fully provide my answer: F# Type Provider for SQL in a class
getDbContext
to internal or private, but not dbSchema
. Any way to not expose it?If I'm not much mistaken, the context is an instance of DataContext, which isn't thread-safe. None of the data context base classes I'm aware of, are thread-safe, and since you want to use them in a web application, you must, at the very least, create one instance per HTTP request; otherwise, the behaviour of your DAL will be defective.
On the other hand, within a single request, it may be worthwhile to reuse the same instance. Therefore, I'd go with this function design:
let insertItem dbContext item =
dbContext.CreateStoredProc(item.Stuff)
because that would let you create a single dbContext
value associated with a single HTTP request, and reuse that for multiple database operations, because you can pass the same dbContext
value to more than one function.
If you want to make all of this accessible from C#, it would be easiest on C# client developers if you wrap all the functionality in classes. Assuming the above insertItem
function, as well as the getDbContext
function from the OP, you could define classes like these:
type ContextShim internal(ctx) =
member x.InsertItem(item : Item) =
insertItem ctx item
type ContextFactory() =
member x.CreateContext connectionString =
let ctx = getDbContext connectionString
ContextShim ctx
This will enable a C# client to use a Singleton instance of the ContextFactory
class, and for each HTTP request, use its CreateContext
method to create an instance of the ContextShim
class, and then use the members on the ContextShim
instance, such as InsertItem
.