【问题标题】:Saving F# types to a database将 F# 类型保存到数据库
【发布时间】:2015-08-08 10:44:35
【问题描述】:

lot 的 f# 文章 recommend 使用 fsharp 的内置类型(例如可区分联合、元组和记录)对域进行建模。一旦我们有了这个模型,如何将它持久化到数据库中?

实体框架和类型提供程序仅适用于具有可变属性的标准类。

【问题讨论】:

    标签: entity-framework f# domain-driven-design


    【解决方案1】:

    您可以将[<CLIMutable>] 属性放在记录上:

    [<CLIMutable>]
    type Foo = { Bar : string; Baz : int }
    

    这将把它变成一个具有可变属性的类,当通过 IL、C# 或 Visual Basic 查看时。从 F# 来看,它看起来仍然是不可变的记录。

    但这并没有真正解决问题,因为没有(反)序列化可区分联合的相应功能。

    (顺便说一句,IIRC,JSON.net 支持 F# 记录和有区别的联合,但到目前为止,这是我知道的唯一例外。)

    在我看来,这是因祸得福,因为领域模型应该与持久性细节解耦

    在 C# 中,您可能认为像实体框架这样的 ORM 提供了这种解耦,但事实并非如此。即使使用所谓的代码优先 POCO 实体,您最终仍会创建 关系 模型,而不是面向对象的模型。想想“导航属性”,这纯粹是关系问题。在 OOD 中,此类属性违反了law of Demeter(我们称它们为 Train Wrecks)。

    如果您想让域模型与实现细节分离,您需要先创建模型,然后再想办法将其持久化。如何做到这一点取决于所使用的持久性技术。

    【讨论】:

    • +1000 "这是因祸得福,因为域模型应该与持久性细节解耦。"。
    • @mark-seeman 如果域和持久性对象是分开的,那么在从数据库中保存/检索数据时,这会不会导致大量的映射代码相互映射?
    • @Kurren 仅当您使用“对象”进行持久性时;)
    • 没有办法将域模型与持久性细节分离。不过,域模型可能能够对其用户隐藏详细信息。其实我相信你不应该太努力去隐藏这个“细节”。现在有一些可用的库允许您测试持久性详细信息(例如查询),而无需进行大量模拟(例如,请参阅 Effort.EF6)。这意味着即使在进行 TDD 时,您也可以接受您的持久性细节,而试图隐藏它们的想法似乎已经过时 (IMO)。
    • @Kurren “在保存/检索数据时,将一个映射到另一个映射代码的整个负载”与处理由 db 模式规定的域模型的恐惧相比,这是一个很小的代价。很遗憾,EF 和其他 ORM 试图假装其他。单一职责原则ftw
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-22
    • 1970-01-01
    • 2016-07-07
    相关资源
    最近更新 更多