DAL中的F#类型提供程序

时间:2015-01-03 04:46:29

标签: c# sql-server f# type-providers

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

  1. F#项目(用于数据访问+其他功能)
  2. C#web项目(将使用F#中的函数)
  3. 我需要调用SQL Server存储过程,并使用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
    2. 我不希望通过F#DAL暴露整个dbContext,只暴露某些存储过程。

      注意:我需要从web.config传递连接字符串

      此处的类似问题并未完全提供我的答案:F# Type Provider for SQL in a class

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

1 个答案:

答案 0 :(得分:3)

如果我没有太多错误,那么上下文就是DataContext的一个实例,它不是线程安全的。我所知道的数据上下文基类都不是线程安全的,并且由于您希望在Web应用程序中使用它们,因此您必须至少为每个HTTP请求创建一个实例;否则,DAL的行为将有缺陷。

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

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

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

如果您希望通过C#访问所有这些内容,那么如果您将所有功能包装在类中,那么对于C#客户端开发人员来说这将是最简单的。假设上面的insertItem函数以及OP中的getDbContext函数,您可以定义这样的类:

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类的Singleton实例,并且对于每个HTTP请求,使用其CreateContext方法创建ContextShim类的实例,然后使用ContextShim实例上的成员,例如InsertItem