从Base扩展数据库对象/向下转发

时间:2014-11-11 04:23:21

标签: f# c#-to-f#

我正在学习F#,并且为了变得更流畅,我正在将后端/数据访问层重新编写到当前正在使用带有ORM的C#的程序中。我正在使用SqlDataProvider类型提供程序(并且喜欢它btw)。

我在F#中对部分类类型的搜索没有出现任何有希望的结果。部分类的原因是为从Sql类型提供程序返回的数据库对象添加一些基本功能。到目前为止,我只是继承了从Sql类型提供程序返回的类型,并以这种方式添加功能。但是,当我从函数返回查询结果时,它返回基类,而不是派生类。

我不想使用反射来映射两个对象的属性,但我也不想返回“new fooObject {......}”并列出每个属性的每个属性时间我想创建一个新方法。

所以我在这里,在世界上所有人都是善的源头。我错过了一些我可以用于部分课堂创作的东西吗?有没有一种简单的方法(不使用反射)将返回的对象映射到派生对象?我完全错过了一些很棒的功能吗?

type DbContext = SqlDataConnection<ConnectionString="~">

//Database objects 
type Address() = 
    //inheriting base class from SqlDataProvider
    inherit DbContext.ServiceTypes.Address()

    //Adding common functionality
    member this.Add()  =
        use db = DbContext.GetDataContext()
        db.Address.InsertOnSubmit this
        db.DataContext.SubmitChanges()

    member this.Remove() = 
        use db = DbContext.GetDataContext()
        db.Address.DeleteOnSubmit this
        db.DataContext.SubmitChanges()

    member this.Update() =
        use db = DbContext.GetDataContext()
        let mutable old = query {for a in db.Address do
                                 where (a.AddressId = this.AddressId)}
                                 |> Seq.exactlyOne 
        old <- this
        db.Address.Context.SubmitChanges()

     //this method only returns the base object
    static member GetAll() =
        use db = DbContext.GetDataContext()
        db.Address |> Seq.toList

     //as does this one
    static member Find addressId = 
        use db = DbContext.GetDataContext()
        let add = new Address()
        query {for a in db.Address do where (a.AddressId = addressId)}
        |> Seq.exactlyOne

1 个答案:

答案 0 :(得分:2)

F#使用type extensions执行此类操作:

type DbContext.ServiceTypes.Address with
    member this.Add() =
        use db = DbContext.GetDataContext()
        db.Address.InsertOnSubmit this
        db.DataContext.SubmitChanges()

    member this.Remove() = 
        use db = DbContext.GetDataContext()
        db.Address.DeleteOnSubmit this
        db.DataContext.SubmitChanges()

    member this.Update() =
        use db = DbContext.GetDataContext()
        let mutable old = query {for a in db.Address do
                                 where (a.AddressId = this.AddressId)}
                                 |> Seq.exactlyOne 
        old <- this
        db.Address.Context.SubmitChanges()

请注意,只能从F#代码访问类型扩展(以此格式)。如果你需要与C#/ VB.Net可互操作的东西,你应该使用&#39; normal&#39;扩展方法:

[<Extension>]
type ExtraCSharpStyleExtensionMethodsInFSharp () =
    [<Extension>]
    static member this.Add (address:DbContext.ServiceTypes.Address)  =
        use db = DbContext.GetDataContext()
        db.Address.InsertOnSubmit address
        db.DataContext.SubmitChanges()

    [<Extension>]
    member this.Remove (address:DbContext.ServiceTypes.Address) = 
        use db = DbContext.GetDataContext()
        db.Address.DeleteOnSubmit address
        db.DataContext.SubmitChanges()

    [<Extension>]
    member this.Update (address:DbContext.ServiceTypes.Address) =
        use db = DbContext.GetDataContext()
        let mutable old = query {for a in db.Address do
                                    where (a.AddressId = this.AddressId)}
                                    |> Seq.exactlyOne 
        old <- address
        db.Address.Context.SubmitChanges()

对于GetAllFind方法,我很想创建一个包含GetAllAddressesFindAddress等函数的模块。

总的来说,存储库模式在F#中有点尴尬。