C# DAL中的F#类型提供程序

C# DAL中的F#类型提供程序,c#,sql-server,f#,type-providers,C#,Sql Server,F#,Type Providers,我有两个项目的解决方案: F#项目(用于数据访问+其他功能) C#web项目(将使用F#的函数) 我需要调用SQL Server存储过程,并使用FSharp.Data.TypeProviders来完成这项工作 类型dbSchema=SqlDataConnection 让getDbContext connString= 匹配字符串 |“”->dbSchema.GetDataContext() |->dbSchema.GetDataContext(connString) 插入: let inser

我有两个项目的解决方案:

  • F#项目(用于数据访问+其他功能)
  • C#web项目(将使用F#的函数)
  • 我需要调用SQL Server存储过程,并使用FSharp.Data.TypeProviders来完成这项工作

    类型dbSchema=SqlDataConnection<“…”,StoredProcedures=true>
    让getDbContext connString=
    匹配字符串
    |“”->dbSchema.GetDataContext()
    |->dbSchema.GetDataContext(connString)
    
    插入:

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

    let insertItem connString项=
    使用dbContext=getDbContext-connString
    dbContext.CreateStoredProc(item.Stuff)
    

  • 我如何从C#中使用它,以便每次插入时都不会重新创建
    dbContext
  • 我不想公开整个
    dbContext
    ,只想通过F#DAL公开某些存储过程

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

    这里类似的问题并不能完全提供我的答案:

  • 我可以将
    getDbContext
    设置为internal或private,但不能将
    dbSchema
    设置为internal或private。有没有办法不暴露它

  • 如果我没弄错的话,上下文是的一个实例,它不是线程安全的。我所知道的所有数据上下文基类都不是线程安全的,因为您希望在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
    类的单一实例,对于每个HTTP请求,使用其
    CreateContext
    方法创建
    ContextShim
    类的实例,然后使用
    ContextShim
    实例上的成员,例如
    InsertItem

    “这样我就不会每次都重新创建dbContext了”为什么不这样做?如果我将它作为第一个插入,那么我可以创建一个dbContext,并像这样传递它:[items]|>Seq.map(insertItem dbContext)我不确定这是否是一个好主意,但不必每次都重新创建上下文是有意义的……此外,在链接的回答中,Tomas说“这为每个工厂创建了一个新的db实例”,这让我觉得这并不理想。1.是的,我在尝试执行[items]>PSeq.map(insertItem dbContext)时发现了线程不安全的部分但它失败了。2.是否仍然需要隐藏SqlDataConnection提供程序使用的dbSchema类型?