DAL 中的 F# 类型提供程序

F# type provider in DAL

我有一个包含 2 个项目的解决方案:

  1. F#项目(用于数据访问+其他功能)
  2. C# web 项目(将使用 F# 中的函数)

我需要调用 SQL 服务器存储过程,我正在使用 FSharp.Data.TypeProviders 来完成这项工作。

type dbSchema = SqlDataConnection< "...", StoredProcedures=true >

let getDbContext connString = 
    match connString with
    | "" -> dbSchema.GetDataContext()
    | _ -> dbSchema.GetDataContext(connString)

插入:

let insertItem dbContext item = 
    dbContext.CreateStoredProc(item.Stuff) 

let insertItem connString item = 
    use dbContext = getDbContext connString
    dbContext.CreateStoredProc(item.Stuff)      
  1. 我如何从 C# 中使用它,这样我就不会在每次插入时都重新创建 dbContext

我不想公开整个 dbContext,只是通过 F# DAL 公开某些存储过程。

注意:我需要传入来自web.config

的连接字符串

这里的类似问题没有完全提供我的答案:F# Type Provider for SQL in a class

  1. 我可以将 getDbContext 设置为内部或私人,但不能 dbSchema。有什么办法不暴露它?

如果我没记错的话,上下文是 DataContext 的一个实例,它不是线程安全的。 None 我所知道的数据上下文库 class 是线程安全的,并且由于您想在 Web 应用程序中使用它们,您必须至少创建一个实例每个 HTTP 请求;否则,您的 DAL 的行为将有缺陷。

另一方面, 单个请求中,重复使用同一个实例可能是值得的。因此,我会采用这种功能设计:

let insertItem dbContext item = 
    dbContext.CreateStoredProc(item.Stuff)

因为这样可以让您创建与单个 HTTP 请求关联的单个 dbContext 值,并将其重复用于多个数据库操作,因为您可以将相同的 dbContext 值传递给多个函数。

如果您想让所有这些都可以从 C# 访问,那么将所有功能包装在 classes 中对 C# 客户端开发人员来说是最简单的。假设上面的 insertItem 函数,以及来自 OP 的 getDbContext 函数,你可以像这样定义 classes:

type ContextShim internal(ctx) =
    member x.InsertItem(item : Item) =
        insertItem ctx item

type ContextFactory() =
    member x.CreateContext connectionString =
        let ctx = getDbContext connectionString
        ContextShim ctx

这将使 C# 客户端能够使用 ContextFactory class 的单例实例,并且对于每个 HTTP 请求,使用其 CreateContext 方法创建 ContextShim class,然后使用ContextShim实例上的成员,如InsertItem.